|
From: | silvioprog |
Subject: | Re: [libmicrohttpd] MHD_quiesce_daemon() question |
Date: | Mon, 27 Mar 2017 22:46:10 -0300 |
bool bf_httpsrv_shutdown(struct bf_httpsrv *srv) {
MHD_socket fd;
uint8_t shutdown_attempts; /* Max 256. */
if (srv && srv->listening) {
fd = MHD_quiesce_daemon(srv->mhd);
if (fd != MHD_INVALID_SOCKET)
close(fd);
else
_BF_LOG("Server quiesce failed.\n");
if (srv->forced_shutdown) {
shutdown_attempts = 1;
while (MHD_get_daemon_info(srv->mhd, MHD_DAEMON_INFO_CURRENT_CONNECTIONS )->num_connections > 0) {
if (shutdown_attempts >= srv->shutdown_attempts) { /* Default srv->shutdown_attempts is 10. */
_BF_LOG("Forced server shutdown.\n");
exit(EINTR);
}
shutdown_attempts++;
sleep(1);
}
}
MHD_stop_daemon(srv->mhd);
srv->listening = false;
return true;
}
return false;
}
On 26.03.2017 8:33, silvioprog wrote:
> I found the following related message:
>
> https://lists.gnu.org/archive/html/libmicrohttpd/2014-09/msg 00012.html
>
> I've used a similar logic, but with item X below, because I need to wait
> the client processing:
>
> 1) MHD_quiesce_daemon()
> *X) while (info.num_connections > 0) sleep(0.5s) # pseudo code*
> 2) MHD_stop_daemon()
> 3) close()
>
> Real implementation:
>
> bool bf_httpsrv_shutdown(struct bf_httpsrv *srv, bool force) {
> MHD_socket fd;
> if (srv && srv->listening) {
> fd = MHD_quiesce_daemon(srv->mhd);
> if (!force)
> while (MHD_get_daemon_info(srv->mhd, MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections > 0) If you don't check returned value from MHD_quiesce_daemon(), you may
> usleep(1000 * 500); //TODO: allow to use external callback
> MHD_stop_daemon(srv->mhd);
> if (fd != MHD_INVALID_SOCKET)
> close(fd);
> srv->listening = false;
> return true;
> }
> return false;
> }
>
>
> Calling it with bf_httpsrv_shutdown(srv, false) the server stops waiting
> for clients processing.
>
> So, what do you think about the logic above? Should it be improved?!
>
> Thanks in advance for any suggestions!
later found that you didn't quiesced daemon, so move check right after
MHD_quiesce_daemon() and added error handling.
If you didn't set connection timeout, connection may live indefinitely.
Moreover, even with connection timeout, clients may continue processing
on same HTTP 1.1 connections with new requests indefinitely.
Furthermore, even with HTTP 1.0 and connection timeout hypothetical
client may read answer very slow with results in very long unpredictable
closure of connection.
So: yes, you code will work but may result in very long (hours, for
example) or even indefinitely long daemon shutdown.
--
Best Wishes,
Evgeny Grin
[Prev in Thread] | Current Thread | [Next in Thread] |