Edit report at http://bugs.php.net/bug.php?id=52848&edit=1

 ID:                 52848
 Comment by:         php dot net at phrozenbyte dot de
 Reported by:        php dot net at phrozenbyte dot de
 Summary:            Processing out-of-band data doesn't work
 Status:             To be documented
 Type:               Bug
 Package:            Streams related
 Operating System:   Ubuntu 10.04 Lucid Lynx
 PHP Version:        5.3.3
 Block user comment: N

 New Comment:

This doesn't help. Maybe it's an issue in my software repository.... I
will fill a bug report on launchpad. Thanks for your help and patience!


Previous Comments:
------------------------------------------------------------------------
[2010-09-17 00:06:22] cataphr...@php.net

Maybe this is a timing issue. Try to start the client only a few seconds
later.

------------------------------------------------------------------------
[2010-09-17 00:05:20] cataphr...@php.net

I can't reproduce this on Debian Lenny:



0: init

0: select

16: $read contains: array(1) {

  [0]=>

  resource(2) of type (stream)

}

16: $except contains: array(0) {

}

16: client connected

16: select

16: $read contains: array(0) {

}

16: $except contains: array(1) {

  [0]=>

  resource(3) of type (stream)

}

16: oob-data: 'a'

16: select

26: $read contains: array(1) {

  [0]=>

  resource(3) of type (stream)

}

26: $except contains: array(0) {

}

26: client disconnected

------------------------------------------------------------------------
[2010-09-16 19:24:42] php dot net at phrozenbyte dot de

I keeped the server script and replaced the client script with yours.
The result:

number of $read sockets: 1

number of $except sockets: 1



There's definitly a issue... Keep the client and try the following
server script:

<?php

$now = time();

$server = stream_socket_server('tcp://127.0.0.1:1234');

echo time()-$now.": init\n";



do {

        $read = $write = $except = array();

        $read[] = $server;

        if(isset($client)) {

                $read[] = $client;

                $except[] = $client;

        }



        echo time()-$now.": select\n";

        stream_select($read, $write, $except, null);

        echo time()-$now.': $read contains: '; var_dump($read);

        echo time()-$now.': $except contains: '; var_dump($except);



        foreach($except as $sock) { // $sock === $client

                echo time()-$now.": oob-data: 
'".stream_socket_recvfrom($client, 1500,
STREAM_OOB)."'\n";

        }



        foreach($read as $sock) {

                if($sock === $server) {

                        $client = stream_socket_accept($server);

                        echo time()-$now.": client connected\n";

                } else { // $sock === $client

                        if(feof($client)) {

                                echo time()-$now.": client disconnected\n";

                                break 2;

                        }

                        

                        $data = stream_socket_recvfrom($client, 1500);

                        echo time()-$now.": data: '".$data."'\n";

                }

        }

} while(true);

?>



The script returns the following (notice the time!):

0: init

0: select

0: $read contains: array(1) {

  [0]=>

  resource(5) of type (stream)

}

0: $except contains: array(0) {

}

0: client connected

0: select

0: $read contains: array(1) {

  [0]=>

  resource(6) of type (stream)

}

0: $except contains: array(1) {

  [0]=>

  resource(6) of type (stream)

}

0: oob-data: 'a'

10: client disconnected



That's wrong! At the second call of stream_select() the $read array
shouldn't contain any socket, only the $except array does because
there's data to read. The time delay between "0: oob-data: 'a'" and "10:
client disconnected" is a result of recv()s blocking. stream_select()
shouldn't fill $read when there's no data to read. The client-side
disconnect affects nothing, that happens (as you can see) 10 seconds
later.

------------------------------------------------------------------------
[2010-09-16 12:40:35] cataphr...@php.net

There's still no bug. Here's a portion of the strace on the server:



socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3

setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0

bind(3, {sa_family=AF_INET, sin_port=htons(1234),
sin_addr=inet_addr("127.0.0.1")}, 16) = 0

listen(3, 32)                           = 0

poll([{fd=3, events=POLLIN|POLLERR|POLLHUP}], 1, 25000) = 1 ([{fd=3,
revents=POLLIN}])

accept(3, {sa_family=AF_INET, sin_port=htons(42533),
sin_addr=inet_addr("127.0.0.1")}, [16]) = 4

select(5, [3 4], [], [4], NULL)         = 2 (in [4]], except [4])



So you call see that the call to select() actually returned the socket
handle in both fd_set structures, as PHP reported.



The reason for returning the socket handle in readfs is that the
connection was closed on the client side. If you don't close the
connection, you get your expected result.



Keep the same code on the server and use this for the client:



<?php

$socket = stream_socket_client('tcp://127.0.0.1:1234');

stream_socket_sendto($socket, 'a', STREAM_OOB);

sleep(10);

fclose($socket);



You now see:



number of $read sockets: 0

number of $except sockets: 1

------------------------------------------------------------------------
[2010-09-16 04:43:44] php dot net at phrozenbyte dot de

Yes, I understand that.

The issue is in a more special case: When the client sends a single byte
(!) with OOB flag, the server will receive 2 recv calls - the first one
including the single byte with OOB flag and the second one is empty
which results in feof() = true.

That means: Even when you send only a single byte with OOB flag, in
which case you can't read non-OOB-data, stream_select() triggers that
you can read non-OOB-data. And this is a issue with php I think.





Client:

---------------

<?php

$socket = stream_socket_client('tcp://127.0.0.1:1234');

stream_socket_sendto($socket, 'a', STREAM_OOB);

fclose($socket);

?>



Server:

---------------

<?php

$server = stream_socket_server('tcp://127.0.0.1:1234');

$socket = stream_socket_accept($server);

$read = array($server, $socket); $write = array(); $except =
array($socket);

stream_select($read, $write, $except, null);

echo 'number of $read sockets: '.count($read)."\n";

echo 'number of $except sockets: '.count($except)."\n";

?>



Expected result:

---------------

number of $read sockets: 0

number of $except sockets: 1



Actual result:

---------------

number of $read sockets: 1

number of $except sockets: 1

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    http://bugs.php.net/bug.php?id=52848


-- 
Edit this bug report at http://bugs.php.net/bug.php?id=52848&edit=1

Reply via email to