Jump to content

Can pcntl_alarm() and socket_select() peacefully exist in the same thread?


DWilliams

Recommended Posts

I have a PHP CLI script mostly written that functions as a chat server for chat clients to connect to (don't ask me why I'm doing it in PHP, thats another story haha).

 

My script utilizes the socket_select() function to hang execution until something happens on a socket, at which point it wakes up, processes the event, and waits until the next event. Now, there are some routine tasks that I need performed every 30 seconds or so (check if tempbanned users should be unbanned, save user databases, other assorted things).

 

From what I can tell, PHP doesn't have very great multi-threading support at all. My first thought was to compare a timestamp every time the socket generates an event and gets the program flowing again, but this is very inconsistent since the server could very well sit idle for hours and not have any of my cleanup routines executed.

 

I came across the PHP pcntl extensions, and it lets me use assign a time interval for SIGALRM to get sent and a function get executed every time it's sent. This seems like the ideal solution to my problem, however pcntl_alarm() and socket_select() clash with each other pretty bad. Every time SIGALRM is triggered, all sorts of crazy things happen to my socket control code.

 

My program is fairly lengthy so I can't post it all here, but it shouldn't matter since I don't believe I'm doing anything wrong code-wise. My question is: Is there any way for a SIGALRM to be handled in the same thread as a waiting socket_select()? If so, how? If not, what are my alternatives here?

 

Here's some output from my program. My alarm function simply outputs "Tick!" whenever it's called to make it easy to tell when stuff is happening. This is the output (including errors) after allowing it to tick 4 times (there were no actual attempts at connecting to the server despite what it says):

 

[05-28-10 @ 20:01:05] Chat server started on 192.168.1.28 port 4050

[05-28-10 @ 20:01:05] Loaded 2 users from file

PHP Notice: Undefined offset: 0 in /home/danny/projects/PHPChatServ/ChatServ.php on line 112

PHP Warning: socket_select(): unable to select [4]: Interrupted system call in /home/danny/projects/PHPChatServ/ChatServ.php on line 116

[05-28-10 @ 20:01:15] Tick!

PHP Warning: socket_accept(): unable to accept incoming connection [4]: Interrupted system call in /home/danny/projects/PHPChatServ/ChatServ.php on line 126

[05-28-10 @ 20:01:25] Tick! PHP Warning: socket_getpeername() expects parameter 1 to be resource, boolean given in /home/danny/projects/PHPChatServ/ChatServ.php on line 129

[05-28-10 @ 20:01:25] Accepting socket connection from PHP Notice: Undefined offset: 1 in /home/danny/projects/PHPChatServ/ChatServ.php on line 112

PHP Warning: socket_select(): unable to select [4]: Interrupted system call in /home/danny/projects/PHPChatServ/ChatServ.php on line 116

[05-28-10 @ 20:01:35] Tick!

PHP Warning: socket_accept(): unable to accept incoming connection [4]: Interrupted system call in /home/danny/projects/PHPChatServ/ChatServ.php on line 126

[05-28-10 @ 20:01:45] Tick!

PHP Warning: socket_getpeername() expects parameter 1 to be resource, boolean given in /home/danny/projects/PHPChatServ/ChatServ.php on line 129

[05-28-10 @ 20:01:45] Accepting socket connection from

PHP Notice: Undefined offset: 2 in /home/danny/projects/PHPChatServ/ChatServ.php on line 112

Link to comment
Share on other sites

It would be best if you could post you code so we can see if perhaps you're doing something wrong. You might want to reevaluate your circumstances and see if you really need timed events. For example, you mention checking to see if someone should be removed from the ban list every X seconds. This doesn't sound necessary. You could just check to see if the user is banned or if his ban period is over when he attempts to login (or connect, however you're identifying the ban).

 

In the case you find it is necessary to have timed events and you can't get pcntl_alarm() working despite implementing it correctly you might want to look making socket_select non-blocking by supplying the optional timeout parameter(s). This way it will return after a certain period of time, and not block indefinitely perhaps solving your problem.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.