#24101 [Fbk->Opn]: socket_select call is blocking and never returning

From: Date: Tue, 10 Jun 2003 13:16:41 +0000
Subject: #24101 [Fbk->Opn]: socket_select call is blocking and never returning
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-41600@lists.php.net to get a copy of this message
ID: 24101 User updated by: wzaccone at telcordia dot com Reported By: wzaccone at telcordia dot com -Status: Feedback +Status: Open Bug Type: Sockets related Operating System: Solaris 5.8 / Sparc PHP Version: 4.3.2 New Comment: Here is the complete function that calls socket_select. we put some tracing (echos) around the socket_select, and saw it never returned. function readMsgsFromHosts($sockets){ // needs to read a "message" from each server where message has the following format: // STX - 1 byte // pad bytes - 1 byte // msg len - 2 bytes // data - variable number of bytes // padding - variable number of bytes - from 0 to 3 // ETX - 1 byte set_time_limit(0); $numSockets = count($sockets); // the following are the available states for the sockets $STXSTATE = 1; $PADBYTES = 2; $MSGLEN = 3; $DATA = 4; $PADDING = 5; $ETXSTATE = 6; $FINISHED = 7; $STX=chr(02); $ETX=chr(03); $socketsPadBytes = array(); $socketsMsgLen = array(); $socketsByteCount = array(); $socketsState = array(); $dataFromSockets = array(); $keys = array_keys($sockets); foreach ($keys as $key){ $socketsPadBytes[$key] = 0; $socketsMsgLen[$key] = 0; $socketsByteCount[$key] = 0; $socketsState[$key] = $STXSTATE; $dataFromSockets[$key] = ""; } $finishedCount = 0; while ($finishedCount != $numSockets){ $socketsCopy = Array(); //$keys = array_keys($sockets); foreach ($keys as $key){ $socketsCopy[$key] = $sockets[$key]; } if (@socket_select($socketsCopy, $w = NULL, $e = NULL, $tv = NULL) !== FALSE){ foreach($socketsCopy as $sock){ $index = array_search($sock, $socketsCopy, true); if ($socketsState[$index] != $FINISHED){ $readAmount = 4; if ($socketsByteCount[$index] >= 4){ $readAmount = $socketsMsgLen[$index] - $socketsByteCount[$index]; } $string = fread($sock, $readAmount); //echo "\n\n<P>Read: ".$string."(".strlen($string)." bytes)<P>\n\n"; if ($string === FALSE){ // error while reading from socket return array("error while reading from socket<P>"); } else if (strlen($string) == 0){ // end of file was reached // shouldn't happen since we use ETX to determine the end of message return array("Reached end of file before ETX<P>"); } else { // data was read from socket while (strlen($string) > 0){ //echo "\n\nString left: " . $string."(".strlen($string)." bytes)<P>\n\n"; if ($socketsState[$index] == $STXSTATE || $socketsState[$index] == ""){ // read in the STX and update state if ($string[0] != $STX){ // error // ignore and keep looping } else { $socketsState[$index] = $PADBYTES; $socketsByteCount[$index] = $socketsByteCount[$index] + 1; } $string = substr($string, 1); } else if ($socketsState[$index] == $PADBYTES){ // read in the pad bytes and update state $socketsPadBytes[$index] = ord($string[0]); $string = substr($string, 1); $socketsState[$index] = $MSGLEN; $socketsByteCount[$index] = $socketsByteCount[$index] + 1; } else if ($socketsState[$index] == $MSGLEN){ // read in the message length and update state if ($socketsMsgLen[$index] == 0){ // have not yet read any msglen info if (strlen($string) == 1){ $socketsMsgLen[$index] = ord($string[0]) * 256; // only a partial read - don't update state $string = substr($string, 1); $socketsByteCount[$index] = $socketsByteCount[$index] + 1; } else { // this should be the normal occurence $socketsMsgLen[$index] = ord($string[0]) * 256 + ord($string[1]); // full read $string = substr($string, 2); $socketsByteCount[$index] = $socketsByteCount[$index] + 2; $socketsState[$index] = $DATA; } } else { // this is the rest of the msg len - add to existing number $socketsMsgLen[$index] = $socketsMsgLen[$index] + ord($string[0]); $string = substr($string, 1); $socketsByteCount[$index] = $socketsByteCount[$index] + 1; $socketsState[$index] = $DATA; } } else if ($socketsState[$index] == $DATA){ // read in data - if bytes read exceeds limit of data then update state // this should read up until $socketsMsgLen[$index] - $socketsPadBytes[$index] - 1 if ($socketsByteCount[$index] + strlen($string) >= $socketsMsgLen[$index] - $socketsPadBytes[$index] - 1){ // need to truncate $string $data = substr($string, 0, $socketsMsgLen[$index] - $socketsPadBytes[$index] - 1 - $socketsByteCount[$index]); $string = substr($string, ($socketsMsgLen[$index] - $socketsPadBytes[$index] - 1 - $socketsByteCount[$index])); $socketsState[$index] = $PADDING; } else { $data = $string; $string = ""; } $dataFromSockets[$index] = $dataFromSockets[$index] . $data; $socketsByteCount[$index] = $socketsByteCount[$index] + strlen($data); } else if ($socketsState[$index] == $PADDING){ // read the padding bytes and update state when finished if ($socketsPadBytes[$index] == 0){ //either this message has no padding or some error occured. // lets assume that there is no padding, shall we? $socketsState[$index] = $ETXSTATE; } else { // read one byte from the string $string = substr($string, 1); $socketsByteCount[$index] = $socketsByteCount[$index] + 1; $socketsPadBytes[$index] = $socketsPadBytes[$index] - 1; if ($socketsPadBytes[$index] == 0){ //echo "Setting state to ETXSTATE<P>\n\n"; $socketsState[$index] = $ETXSTATE; } } } else if ($socketsState[$index] == $ETXSTATE){ //echo "Reading ETX<P>"; if ($string[0] != $ETX){ // illegal end character // ignore and keep looping //echo "Illegal end character"."<P>"; } else { $socketsState[$index] = $FINISHED; $socketsByteCount[$index] = $socketsByteCount[$index] + 1; } $string = substr($string, 1); // update $finishedCount variable $finishedCount++; } else { //print_r($dataFromSockets); return array("<HR>Error: reached an undefined state<P>"); } } } } else { // already finished so don't read anything from this socket } } } else { // error condition return array("error in select<P>"); } } // all the sockets have been completely read return $dataFromSockets; } Previous Comments: ------------------------------------------------------------------------ [2003-06-09 23:40:31] sniper@php.net Could you give a complete (but short, please) script that shows this problem clearly..? (can't reproduce, but I'm propably missing some part here..) ------------------------------------------------------------------------ [2003-06-09 14:02:38] wzaccone at telcordia dot com we upgraded our application from php 4.1.2 to 4.3.2 and are testing. and found the following code no longer works: if (@socket_select($socketsCopy, $w = NULL, $e = NULL, $tv = NULL) !== FALSE){ foreach($socketsCopy as $sock){ The socket_select call appears to be never returning with php 4.3.2.. code worked correctly with 4.1.2. ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=24101&edit=1

« previous php.bugs (#41600) next »