php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #42343 socket_set_option code example is misleading
Submitted: 2007-08-19 21:50 UTC Modified: 2007-08-20 16:00 UTC
From: mpb dot mail at gmail dot com Assigned: nicobn (profile)
Status: Closed Package: Documentation problem
PHP Version: Irrelevant OS: Linux/Irrelevant
Private report: No CVE-ID: None
 [2007-08-19 21:50 UTC] mpb dot mail at gmail dot com
Description:
------------
On this page:

http://www.php.net/manual/en/function.socket-set-option.php

Example 2275. socket_set_option() example

The example is misleading.  To be useful, SO_REUSEADDR must be set before bind.  However, socket_create_listen calls bind (internally) before SO_REUSEADDR is set.

So, if you:

1) run the (modified) script (the Reproduce code)
2) connect (via another process, say a manual telnet)
3) (the script will exit after socket_accept)
4) then re-run the script

In step 4, socket_create_listen will fail, because SO_REUSEADDR is NOT set when socket_create_listen is called.

So, basically, unless socket_create_listen *automatically* and *invisibly* sets SO_REUSEADDR for us, we cannot meaningfully use SO_REUSEADDR in combination with socket_create_listen.

Probably socket_create_listen should be extend with another (boolean) parameter so that we can tell it whether or not to set SO_RESUEADDR.

But, at the very least the docs should be fixed.

Additionally, the logic is flawed.  On error, socket_get_option returns NULL, and (NULL !== 0) is true, so the example prints "SO_REUSEADDR is set on socket !", even though there is *no* socket!.

Additionally, the docs say that socket_get_option should return false on error, but on my machine (PHP 5.2.3) it returns NULL.

That's a lot of bugs!

Reproduce code:
---------------
<?php
$socket = socket_create_listen(1223);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);

if (socket_get_option($socket, SOL_SOCKET, SO_REUSEADDR) !== 0) {
    echo 'SO_REUSEADDR is set on socket !' . PHP_EOL;
}

// I add the following line so we can actually connect.
socket_accept ($socket);

?> 

Expected result:
----------------
SO_REUSEADDR is set on socket !


Actual result:
--------------
PHP Warning:  socket_create_listen(): unable to bind to given adress [98]: Address already in use in <snip>/test.php on line 2
PHP Warning:  socket_set_option() expects parameter 1 to be resource, boolean given in <snip>/test.php on line 3
PHP Warning:  socket_get_option() expects parameter 1 to be resource, boolean given in <snip>/test.php on line 5
SO_REUSEADDR is set on socket !
PHP Warning:  socket_accept() expects parameter 1 to be resource, boolean given in <snip>/test.php on line 10


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-08-19 22:56 UTC] nicobn@php.net
You are right for the binding part and the documentation will be changed to reflect this soon. On the other side, the rest of your bug report is not right.

The reason socket_set_option() returns NULL is because the parameter is not a socket resource if you run your example twice (because SO_REUSEADDR was not set, of course). The parameter parsing fails and NULL is returned. In a real-world situation, you always check if the resource is not NULL when you pass it as a parameter. By the way, all the socket functions return NULL if they are not passed proper parameters. In all cases, if there is an error with the function itself (and not its parameters), FALSE is returned by this function (you can look at the source to convince yourself).

As for the flawed logic well... it isn't. Socket flags have a numeric value and always had. In this example, when socket_create_listen() fails, it returns NULL, not a flag value. 

The only bug is the example, thank you for the heads up, but that's not "a lot of bugs". 
 [2007-08-20 03:59 UTC] nicobn@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.

Also, just fyi, the reason I compare with !== 0 is because the ONLY thing that we're sure of is that, if a flag is set, it is going to be non-null and if it is not set, it is going to be 0. Will the actual result of socket_get_option be 1 or 122306 ? We don't really know.
 [2007-08-20 08:04 UTC] mpb dot mail at gmail dot com
Hi nicobn,

> The reason socket_set_option() returns NULL is because the parameter
> is not a socket resource

The docs say socket_get_option():

"Returns the value of the given option, or FALSE on errors."

If socket_get_option() is correctly returning NULL, then the docs are
wrong and inaccurate, because the docs do not describe this behavior.

> By the way, all the socket functions return NULL if they are not
> passed proper parameters.

If this is the desired behavior, the docs should reflect it
everywhere.  Anything less is inaccurate documentation.

> As for the flawed logic well... it isn't. Socket flags have a numeric
> value and always had. In this example, when socket_create_listen()
> fails, it returns NULL, not a flag value.

> Also, just fyi, the reason I compare with !== 0 is because the ONLY
> thing that we're sure of is that, if a flag is set, it is going to be
> non-null and if it is not set, it is going to be 0. Will the actual
> result of socket_get_option be 1 or 122306 ? We don't really know.

You write:

if (socket_get_option($socket, SOL_SOCKET, SO_REUSEADDR) !== 0) {

But FALSE !== 0 is true!  And socket_get_option can return FALSE on error!  (And NULL !== 0 is true!  And socket_get_option can return NULL on input errors!)

I claim the following is both functionally correct and more readable:

if (socket_get_option($socket, SOL_SOCKET, SO_REUSEADDR)) {

Thanks for fixing the docs!

-mpb
 [2007-08-20 15:23 UTC] nicobn@php.net
Thank you for your concern, but when a wrong parameter is passed to a function, it always return NULL as this is not really an error with the function: it is an error with the parameter parser. All the functions behave the same and, as such, I am not going to change the thousands of functions pages in the manual but I will voice your concern to the manual editor.

If you really want to go at it and make a perfect real-world test-case, you'd have to do something like:

$rval = socket_get_option($socket, SOL_SOCKET, SO_REUSEADDR);

if (!is_integer($rval)) {
    echo "There was an error with the parser or with the function" . PHP_EOL;
} else if ($rval !== 0) {
    echo "SO_REUSEADDR is set on socket !" . PHP_EOL;
}

My initial example was loose: I figured that if you have 3 error messages on the screen, you easily understand that socket_create() failed and that, as such, you should not really expect socket_get_option() to work and/or to return a meaningful result. I understand this can be misleading so I'll commit the example with error handling.
 [2007-08-20 16:00 UTC] nicobn@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.


 [2020-02-07 06:10 UTC] phpdocbot@php.net
Automatic comment on behalf of nicobn
Revision: http://git.php.net/?p=doc/en.git;a=commit;h=6164d642adacc3064a997aa76fcb1e52a8aef921
Log: Fixed bug #42343
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Wed Nov 19 12:00:02 2025 UTC