Hi Mike, Good point. The behaviour must be documented correctly, of course.
For me, seems logical to close everything in case of failure, like with MHD_daemon_destroy(). Typical application logic does not use any kind of fallback paths, like "if daemon failed with these options, let's try to start with other options". Without a fallback path, it makes sense to perform a clean-up in MHD, as it is done in other situations, so the application would never need to perform a clean-up for resources used to create the daemon.
The lack of information about which part is failed is a real problem, however with v0.x/v1.x API it cannot be solved nicely.
MHD version 2.x (currently in alpha stage) gives concrete error code with indication of failed component or function.
The code for v1.x will be fixed to close the socket always (unless there are strong arguments against it) and documented correctly.
Thank you for your feedback. -- Evgeny On 02.09.2025 22:31, Mike Crowe via libmicrohttpd wrote:
As far as I can see the documentation for the MHD_OPTION_LISTEN_SOCKET option to MHD_start_daemon() doesn't say whether the passed socket is left open if MHD_start_daemon() fails and returns NULL. In v1.0.2, MHD_start_daemon() does close the socket if an incorrect password is supplied with MHD_OPTION_HTTPS_KEY_PASSWORD because failure of MHD_TLS_init() jumps to free_and_fail which always closes listen_fd. It looks like there's a clear divide where failures above and including the call to MHD_mutex_init_() manually free memory and return immediately (so they don't close the socket) whereas failures below that call jump to free_and_fail (which does close the socket) or to thread_failed which calls MHD_stop_daemon() (which also closes the socket). Unfortunately the caller has no idea what the failure was when MHD_start_daemon() returns, so it can't tell whether it needs to close the socket itself. All things being equal I would argue that it is more logical for MHD_start_daemon() to never close the socket on failure, but I suspect that this would be harder to implement in the current code so consistently closing on failure would be better than the current situation. Should free_and_fail always be being jumped to rather than manual freeing and returning to make the behaviour consistent so that callers can always do the right thing? Thanks. Mike.
