English 中文(简体)
PHP: Can pcntl_alarm() and socket_select() peacefully exist in the same thread?
原标题:

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

最佳回答

pcntl_alarm and socket_select can coexist, but you need to be aware of how to do it right.

In particular, if the alarm goes off while socket_select() is waiting, then after the alarm is handled the socket_select() will return immediately with an error indication. The error is "Interrupted System Call", which is what you re seeing in the output. You need to specifically check for that error, and retry the socket_select().

Alternatively, you can just forget about using the alarm and instead use the timeout facility of socket_select(). This is what the tv_sec parameter is for - it gives a timeout in seconds, after which the socket_select() will return even if no sockets are ready. You can then do your regular processing.

问题回答

暂无回答




相关问题
Signed executables under Linux

For security reasons, it is desirable to check the integrity of code before execution, avoiding tampered software by an attacker. So, my question is How to sign executable code and run only trusted ...

encoding of file shell script

How can I check the file encoding in a shell script? I need to know if a file is encoded in utf-8 or iso-8859-1. Thanks

How to write a Remote DataModule to run on a linux server?

i would like to know if there are any solution to do this. Does anyone? The big picture: I want to access data over the web, using my delphi thin clients. But i´would like to keep my server/service ...

How can I use exit codes to run shell scripts sequentially?

Since cruise control is full of bugs that have wasted my entire week, I have decided the existing shell scripts I have are simpler and thus better. Here is what I have so far svn update /var/www/...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

热门标签