4

I'm working with a class that makes a remote connection to a server. A problem that I'm running into is if the connection doesn't get a response, it'll wait until it does.

This class does not have a timeout built into it, and I don't want to modify it if I can avoid it.

Is there any way that I can wrap a section of code in something like this?

try(timeout seconds){
}catch(){
    //exception handle
}timeout(){
    // timeout handline
}

EDIT: I use the remote connection as one problem. I have others that I need to solve with this as well, like making system calls with exec or other similar things.

Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
Ben Dauphinee
  • 4,061
  • 8
  • 40
  • 59
  • Could you do an asynchronous call instead? – nico Aug 15 '11 at 15:45
  • 1
    @nico how would you do that in PHP? No multithreading, no guarantee of pcntl_fork() being available, and many resource types not supporting non-blocking modes... if you know of a way to do it with PHP core only I would dearly love to hear it (I didn't mean this comment to come off as sarcastic as it has done...) – DaveRandom Aug 15 '11 at 15:49
  • Ben, what is the underlying function that is connecting to the remote server within the class? All the connect functions in the socket extension have timeout parameters, as does `fsockopen()`, and you can use `stream_set_timeout()` with stream resources or `socket_set_option($socket,SOL_SOCKET,SO_RCVTIMEO,$timeout)` with the sockets extension for subsequent operations... – DaveRandom Aug 15 '11 at 15:53
  • 1
    It might be possible to have a separate script on the server dedicated to handling the remote connections - to set up a connection, you'd send a request to the other script (with a timeout on the request). If the remote connection script failed to finish before the timeout, the original script could detect it and move on. – Sam Dufel Aug 15 '11 at 15:56
  • @DaveRandom: I am obviously speaking of doing the call asynchronously client side. – nico Aug 15 '11 at 16:14

1 Answers1

2

Not for only a section of the code.

There is however alternative solutions, without modifying the original code, as requested:

set_time_limit

set_time_limit() will abort the whole script if it runs for too many time. You could still setup a shutdown function.

pcntl_alarm

pcntl_alarm() will send you a signal after a given amount of time, which may abort the blocking syscall the class is doing at that time, and this may allow you to ask the class to abort its operations if it provides such method. This may not be suitable in a web server environment, though.

Default timeouts

If the class is using stream functions, you may be able to set a default timeout:

ini_set('default_socket_timeout', 5);
stream_context_set_default(array(
    'http' => array(
        'timeout' => 5, 
    ),
));

Execute in a separate process

You could fork with pcntl_fork(), but this is not suitable in a server environment.

You could also use proc_open or popen to execute a PHP script in a separate process and kill it if it runs for a too long time. (After the process is spawned, do an idle wait on the process' stdout stream with stream_select.)

Or setup a server for handling these tasks.

Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194