Dude, thanks for fixing it, I'm going to study the changes and apply it
here. :-)

I've got a situation that locks the shutdown even using this fix, but I
need to create a small project simulating the problem, I'm going to do it
now ...

On Tue, Mar 28, 2017 at 12:08 PM, Evgeny Grin <k...@yandex.ru> wrote:

> Fixed version of you code:
>
> 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) {
> srv->listening = false; close(fd); 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");
> break; } shutdown_attempts++; sleep(1); } } } else _BF_LOG("Server
> quiesce failed.\n"); MHD_stop_daemon(srv->mhd); return true; } return
> false; }
>
> --
> Best Wishes,
> Evgeny Grin
>
> On 28.03.2017 4:46, silvioprog wrote:
> > Thanks for replying Evgeny, you and Christian always saving my day. :-)
> > I read and re-read your and Christian answer, and finally I found a
> > possible way to never lock the server at shutdown: adding an option to
> > exit the server after configurable attempts. It can solve the timeout
> > problem too, because I can't ensure that the programmer have
> > configured it (anyway my library will assume 15 seconds by default).
> > So, the code below applies your tips and implements the attempts
> approach:
> > 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; }
> > Unfortunately if exit was called the MHD_stop_daemon() will be not
> > called, probably raising some memory leak, but current I have no idea
> > how it could be solved.
> > Feel totally free to point improvements about this new version. :-)
> > On Sun, Mar 26, 2017 at 5:36 PM, Evgeny Grin <k...@yandex.ru
> > <mailto:k...@yandex.ru>> wrote:
> >
> >     On 26.03.2017 8:33, silvioprog wrote: > I found the following
> >     related message: > >
> >     https://lists.gnu.org/archive/html/libmicrohttpd/2014-09/
> msg00012.html
> >     <https://lists.gnu.org/archive/html/libmicrohttpd/
> 2014-09/msg00012.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) >
> >                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! If you don't check
> >     returned value from MHD_quiesce_daemon(), you may 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
> >
> >
> > --
> > Silvio Clécio
>

-- 
Silvio Clécio

Reply via email to