dbus-daemon on Windows: Failed to bind socket "localhost:59367": Address already in use

Thomas Sondergaard ts at medical-insight.com
Sat Jan 3 05:22:56 PST 2015


Hi Ralf,

On 2015-01-03 10:24, Ralf Habacker wrote:
>
> Am 03.01.2015 um 01:43 schrieb Thomas Sondergaard:
>> On 2015-01-02 23:17, Thomas Sondergaard wrote:
>>> When I run the attached test programs I get a handful or so of cases
>>> where the dbus-daemon fails to start with a message like
>>>
>>> Failed to bind socket "localhost:59367": Address already in use
>>>
>>> This surprises me. First I thought it was some kind of race condition
>>> when starting multiple buses at the same time (dbus-test.cc), but it
>>> also fails a handful of times out of a thousand when only one process is
>>> started at a time (dbus-test-nothreads.cc).
>>>
>>> This is using D-Bus Message Bus Daemon 1.8.10 on Windows.
>>>
>>> Steps to reproduce:
>>>
>>> 1. Compile the small test program on Windows
>>> 2. Make sure dbus-daemon is in the path
>>> 3. Run the test program
>>>
>>> The nothreads version takes about 4 minutes to run.
>>>
>>> Regards,
>>> Thomas
>>
>> I've digged a little further and I think I see a bug in
>> _dbus_server_new_for_tcp_socket() in dbus-sysdeps-win.c. If I
>> understand _dbus_server_new_for_tcp_socket() it is working hard to
>> bind the same port on both IPv4 and IPv6. If it starts with port=0 it
>> will do a bind with that and then extract the port number with
>> getsockname(), and then it will goto redo_lookup_with_port and do the
>> same binds again.
>>
>> The bug that I'm seeing is that it is not correctly extracting the
>> port number that the first bind with port=0 produces. It is doing:
>>
>> snprintf( portbuf, sizeof( portbuf ) - 1, "%d", addr.AddressIn.sin_port);
>>
>> which fails to account for sin_port being in network byte order. The
>> effect is that subsequent binds will be to another "arbitrary" port
>> that may or may not be available.
>>
>> Just adding ntohs() around addr.AddressIn.sin_port will make the
>> function find the correct port, but it wont work as the next bind()
>> will then fail with EADDRINUSE.
>>
>> I compared the Windows and the Unix version of
>> _dbus_server_new_for_tcp_socket() and it seems that the two versions
>> of the functions have grown apart over time. Perhaps the unix version
>> has some tricks that the Windows version needs to learn?
> The difference in _dbus_listen_tcp_socket is that the unix version uses
> getnameinfo() to fetch the port, which is implemented in the appended
> patch for windows too. Can you check if this works ?
>
> Regards
>   Ralf
>

It doesn't work. The second call to bind after the port number chosen by 
the kernel has been obtained fails. I have stolen another fragment from 
the unix version of the function and it now works correctly. See 
attached patch.

Regards,
Thomas

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Bind-correctly-to-ephemeral-port.patch
Type: text/x-patch
Size: 3097 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/dbus/attachments/20150103/c81d0d6e/attachment.bin>


More information about the dbus mailing list