Bug #78038 [Csd]: Socket_select fails when resource array contains references

From: Date: Thu, 23 May 2019 09:16:35 +0000
Subject: Bug #78038 [Csd]: Socket_select fails when resource array contains references
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-220962@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=78038&edit=1 ID: 78038 Updated by: nikic@php.net Reported by: ogdg at protonmail dot com Summary: Socket_select fails when resource array contains references Status: Closed Type: Bug Package: Sockets related Operating System: Fedora 30 PHP Version: 7.3.5 -Assigned To: +Assigned To: nikic Block user comment: N Private report: N New Comment: I've fixed the issue with the reference handling, and think it's pretty likely that this is what's causing the problem for you. There's likely some singleton references lying around in your socket array that won't even show up in var_dump (e.g. if you do a by-ref iteration over the sockets or similar). If the issue persists after this fix, let's take another look. Previous Comments: ------------------------------------------------------------------------ [2019-05-23 09:13:40] nikic@php.net Automatic comment on behalf of nikita.ppv@gmail.com Revision: http://git.php.net/?p=php-src.git;a=commit;h=9a74b23297167ca7956fd21428c8b987e7d99aa5 Log: Fixed bug #78038 socket_select with references ------------------------------------------------------------------------ [2019-05-23 07:58:49] nikic@php.net > So in this case, 6a fails with the warnings listed in the original report, while 6b works fine. > In the actual application, the socket array is passed to a custom function by reference...but I did > try passing it directly and the result was the same in 6a. From looking at the code, I suspect that the problem does have something to do with references being introduced somewhere. At least we're missing a DEREF in here: https://github.com/php/php-src/blob/2e4686b5667e9ccbfbfab10452c42f5b818fcfdb/ext/sockets/sockets.c#L906 ------------------------------------------------------------------------ [2019-05-23 07:33:28] ogdg at protonmail dot com @nikic The latest version I was using that did not have this issue was 7.2, and it never happened in any of the version 5 series. I am using the version that is included with Fedora 30 standard repos without any modifications or custom extensions. Just the default install. @daverandom I made a short script to simulate what my application does but the error does not occur. The actual application is using AF_UNIX type sockets for IPC. I do not have the free time to reproduce a full-blown script of this sort right now, but the bug is still present. The application where this issue happens has the basic structure like this: 1) Main process creates AF_UNIX socket 2) Sub process launched, create their own AF_UNIX socket and connect to the main process socket 3) Main process does a socket_accept for new IPC connections 4) Main process uses a this to get PID of child process: $pid = socket_get_option($conn, SOL_SOCKET, 17); $pid = (int)$pid; 5) The main process keeps a copy of the resource in an array indexed by PIDs. $socketArray['ipc'][$pid]; 6a) Problem happens when I take that array and do this: $e = $w = NULL; $r = $socketArray['ipc']; socket_select($r, $w, $e, 0); 6b) To fix this, I had to manually loop through the resource array: foreach($socketArray['ipc'] as $v) $r[] = $v; ... So in this case, 6a fails with the warnings listed in the original report, while 6b works fine. In the actual application, the socket array is passed to a custom function by reference...but I did try passing it directly and the result was the same in 6a. Both print_r and var_dump show that the array is being correctly assigned in 6a, and that $r does indeed contain resources, which is why the fix in 6b works. I can't really tell what the problem is, but it's definitely there and seems to appear in very specific conditions. My first guess was that the $pid wasn't being cast to INT and was being treated as a string, so I cast it to INT and that didn't help. The other thing I thought could be a problem is the large numeric values for the $pid, meaning that for some reason socket_select chokes when the index values of any connection array are above a certain number, but I couldn't reproduce this in a standalone script just using large index values for socket_select...also, the standalone script is not using pcntl_fork as the actual application does. ------------------------------------------------------------------------ [2019-05-22 07:44:17] nikic@php.net One recent change comes to mind here: https://github.com/php/php-src/commit/bdac9ef10d90997f9576564dde693cbef6594142#diff-9df410db21c230cd2ec04a4c95ccd20f However, it is in stream_select(), not socket_select(). When you say "previous versions" do you mean 7.3.4 or some older version? ------------------------------------------------------------------------ [2019-05-20 10:00:10] daverandom@php.net Thank you for this bug report. To properly diagnose the problem, we need a short but complete example script to be able to reproduce this bug ourselves. A proper reproducing script starts with <?php and ends with ?>, is max. 10-20 lines long and does not require any external resources such as databases, etc. If the script requires a database to demonstrate the issue, please make sure it creates all necessary tables, stored procedures etc. Please avoid embedding huge scripts into the report. I cannot reproduce this in 7.3.5 or any other version. Additionally, none of the relevant code in php-src has been changed for several years in 7.3[1] or master[2]. Please recheck your code, var_dump($r) and verify that it contains at least one valid socket resource, and if so please provide a complete reproducing script. There is a lot of code in the wild which utilises a pattern roughly like below - it's likely that if it were broken then a lot of people would be shouting about it :-) $socket = socket_create(/* stuff */); // ...set up the socket $sockets[(int)$socket] = $socket; // Add socket to array indexed by resource ID $w = $e = NULL; $r = $sockets; $check = socket_select($r, $w, $e, 0); [1] https://github.com/php/php-src/blame/PHP-7.3/ext/sockets/sockets.c#L915-L977 [2] https://github.com/php/php-src/blame/master/ext/sockets/sockets.c#L921-L983 ------------------------------------------------------------------------ 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 https://bugs.php.net/bug.php?id=78038 -- Edit this bug report at https://bugs.php.net/bug.php?id=78038&edit=1

« previous php.bugs (#220962) next »