php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #64654 socket_select returns false and socket_last_error returns 0 (success)
Submitted: 2013-04-17 09:52 UTC Modified: 2013-04-20 15:08 UTC
Votes:2
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: xilon dot jul at gmail dot com Assigned: cataphract (profile)
Status: Not a bug Package: Sockets related
PHP Version: 5.4.14 OS: Linux 3.5.0-23-generic
Private report: No CVE-ID: None
 [2013-04-17 09:52 UTC] xilon dot jul at gmail dot com
Description:
------------
When a socket ressource previously watched for read I/O in socket_select is 
closed, the socket_select function would return false and throw a warning saying 
"Not a valid socket ressource".

The fact is that subsequent call to socket_last_error() returns 0 which translates 
to success using socket_strerror().


Test script:
---------------
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if (false === socket_bind($socket, '0.0.0.0', 5555)) {
	die('bind()');
}
$read[] = $socket;
// voluntarily close the socket
socket_close($socket);
// Will throw a warning and return false
$retval = socket_select($read, $w = null, $e = null, 1);
echo socket_last_error(); // returns 0


Expected result:
----------------
As the C select system call, closing the socket should return a valid system error 
code.

The C counterpart of this PHP sample above gives :

select(): Bad file descriptor (9 => EBADF)



Actual result:
--------------
The result of socket_last_error is 0.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-04-17 13:59 UTC] laruence@php.net
I don't think this is a bug.

the warning is threw before do really "select", it is an error in php side. not 
system call side.

and socket_last_error is for the error in system call side.
 [2013-04-17 16:00 UTC] xilon dot jul at gmail dot com
Thanx laruence for your answer. I also "straced" the sample to check if the real 
sys call was invoked and indeed it is not. Php does some processing before 
giving the hand to the select sys call (checking valid fd, raising a warning as 
you mentionned).

However to give more control on Php side, I think a return code different from 0 
must be returned. Even if it's not a "bug", my opinion is that there is a  
misconception here about raising a warning and having a success return code and 
that thinking that all that should be fined enough for PHP developpers.
 [2013-04-18 05:40 UTC] laruence@php.net
hmm, I agree with you about give more info to php side.

but what do we define this error ? E_BADF?

simple fix is:

$ git diff
diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c
index f305fa0..5f5b8c2 100644
--- a/ext/sockets/sockets.c
+++ b/ext/sockets/sockets.c
@@ -783,7 +783,14 @@ static int php_sock_array_to_fd_set(zval *sock_array, fd_set 
*fds, PHP_SOCKET *m
 		num++;
 	}

-	return num ? 1 : 0;
+	if (num) {
+		return 1;
+	} else {
+#ifdef EBADF
+		SOCKETS_G(last_error) = EBADF;
+#endif
+		return 0;
+	}
 }
 /* }}} */
 [2013-04-18 09:23 UTC] xilon dot jul at gmail dot com
hey laruence, first of all thanx four your involvement.
I've applied your patch against PHP 5.4.14 and executed the test script again, 
it works as it should.

socket_last_error now returns 9 which is what is expected.

A big thanx for your work.
What are the future actions now ? Should this bug fix be planned in a future php 
version ?
 [2013-04-18 13:43 UTC] laruence@php.net
-Assigned To: +Assigned To: cataphract
 [2013-04-18 13:43 UTC] laruence@php.net
@cataphract, do you think this fix makes sense?

if no objection, I will commit it into 5.4+

thanks
 [2013-04-20 15:08 UTC] cataphract@php.net
I would not change anything here. The problem is that the
socket resource at that point is not valid anymore. Its
value:

	resource(5) of type (Unknown)

If we are changing this, then all the socket functions
should set an EBAF when something other than a socket file
descriptor is passed. But we don't do that because argument
errors, usually detected at the zend_parse_parameters stage,
usually fail early, emit a message and function returns null
or false.

In this case, because we expect arrays of socket resources
and not just a socket resource, the check cannot be done
inside zend_parse_parameters. But I don't see why the
behavior should be different.

Marking as not a bug.
 [2013-04-20 15:08 UTC] cataphract@php.net
-Status: Assigned +Status: Not a bug
 
PHP Copyright © 2001-2022 The PHP Group
All rights reserved.
Last updated: Tue Jan 25 06:03:33 2022 UTC