This problem was detected by Valgrind 3.25.1 when running one of the test
cases for our code that uses libmicrohttpd.

In v1.0.1 if the bind() call in MHD_start_daemon_va fails then listen_fd is
closed and set to an invalid value at daemon.c line 8433:

     if (0 != bind (listen_fd, pservaddr, addrlen))
     {
 #ifdef HAVE_MESSAGES
       MHD_DLOG (daemon,
                 _ ("Failed to bind to port %u: %s\n"),
                 (unsigned int) port,
                 MHD_socket_last_strerr_ ());
 #endif
       MHD_socket_close_chk_ (listen_fd);
       listen_fd = MHD_INVALID_SOCKET;
       goto free_and_fail;
     }

Unfortunately, listen_fd has already been copied to daemon->listen_fd by
daemon.c line 8399:

     /* check for user supplied sockaddr */
     daemon->listen_fd = listen_fd;

That copy is closed again at the end of MHD_start_daemon_va at
daemon.c line 9041:

  if ((MHD_INVALID_SOCKET != daemon->listen_fd) &&
       (listen_fd != daemon->listen_fd))
     (void) MHD_socket_close_ (daemon->listen_fd);

It doesn't look like the code has changed in this area on current master.

My instinct is to push copying listen_fd to daemon->listen_fd close to the
end of MHD_start_daemon_va. Unfortunately it seems that listen_fd is read
back from daemon->listen_fd in certain circumstances. It is not a simple
function!

Is there a straightforward fix for this that I've missed?

Thanks.

Mike.

Original Valgrind report:
--8<--
 ==2700784== File descriptor 13: AF_INET6 socket 13: <unbound> <-> <unbound> is 
already closed
 ==2700784==    at 0x792BD6C: close (close.c:27)
 ==2700784==    by 0x4E5AE64: MHD_start_daemon_va (daemon.c:9041)
 ==2700784==    by 0x4E5AF1A: MHD_start_daemon (daemon.c:6116)
 ==2700784==  Previously closed
 ==2700784==    at 0x792BD6C: close (close.c:27)
 ==2700784==    by 0x4E59B9F: MHD_start_daemon_va (daemon.c:8433)
 ==2700784==    by 0x4E5AF1A: MHD_start_daemon (daemon.c:6116)

Reply via email to