[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [libmicrohttpd] minor issue with epoll+externalselect+no_timeout
From: |
Christian Grothoff |
Subject: |
Re: [libmicrohttpd] minor issue with epoll+externalselect+no_timeout |
Date: |
Thu, 19 Jun 2014 17:35:41 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Icedove/24.5.0 |
Ah, I see. Should be fixed in SVN 33735.
Happy hacking!
Christian
On 06/19/2014 09:07 AM, Marcos Pindado Sebastian wrote:
> Hi Christian!,
>
> I am using version 0.9.34, but to align to the tests you suggest I have
> downloaded version 0.9.37 and the results are the same.
>
> Daemon flags:
> MHD_USE_SUSPEND_RESUME|MHD_USE_DEBUG|MHD_USE_EPOLL_LINUX_ONLY|MHD_USE_EPOLL_TURBO
>
> Debugging MHD_start_daemon I see setup_epoll_to_listen is called during
> MHD_start_daemon_va:
>
> Breakpoint 1, setup_epoll_to_listen (daemon=0x61a010) at daemon.c:3232
> 3232 {
>
> but the socket_fd is still -1 and this function returns with no error
>
> 3249 if (MHD_INVALID_SOCKET == daemon->socket_fd)
> 3250 return MHD_YES; /* non-listening daemon */
> (gdb) p daemon->socket_fd
> $1 = -1
>
> Then again in MHD_start_daemon_va jump to 3550
>
> 3550 if ( (MHD_INVALID_SOCKET == daemon->socket_fd) &&
> 3551 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
> (gdb) p daemon->options & MHD_USE_NO_LISTEN_SOCKET
> $2 = 0
>
> And then creates the socket_fd:
>
> 3558 socket_fd = create_socket (daemon,
> 3559 PF_INET, SOCK_STREAM, 0);
>
> So setup_listen for this case is called before the socket_fd is set up and it
> is not attached to the epoll descriptor.
>
> Invoking MHD_run once after daemon is created, the socket_fd is attached to
> the epoll:
>
> 2465 if ( (MHD_INVALID_SOCKET != daemon->socket_fd) &&
> 2466 (0 != daemon->max_connections) &&
> 2467 (MHD_NO == daemon->listen_socket_in_epoll) )
> 2468 {
> 2469 event.events = EPOLLIN;
> 2470 event.data.ptr = daemon;
> 2471 if (0 != epoll_ctl (daemon->epoll_fd,
> 2472 EPOLL_CTL_ADD,
> 2473 daemon->socket_fd,
>
>
> Thanks!
>
> Marcos
> ________________________________________
> De: address@hidden address@hidden en nombre de Christian Grothoff
> address@hidden
> Enviado el: miércoles, 18 de junio de 2014 21:12
> Para: address@hidden
> Asunto: Re: [libmicrohttpd] minor issue with epoll+external
> select+no_timeout
>
> Hi!
>
> Interesting workaround, but obviously this is not how it should be.
>
> However, I am not sure I can see how this happens. In daemon.c:3537
> MHD_start_daemon_va() makes a call to 'setup_epoll_to_listen()' and in
> that function in line daemon.c:3253 the listen FD is added to the epoll
> set..=0A
> For the combination of flags you state, I do not quite see how the
> respective paths would not be taken (without triggering a jump to
> 'free_and_fail' which means MHD_start_daemon() would return NULL).
>
> So to further understand, analyze and hopefully improve the situation,
> could you say which version of MHD are you using, and --- especially if
> you are using a release >= 0.9.35 --- could you please try to use gdb to
> see how MHD runs through the MHD_start_daemon()-routine without
> triggering the epoll call in line 3253?
>
>
> Happy hacking!
>
> Christian
>
> On 06/18/2014 11:40 AM, Marcos Pindado Sebastian wrote:
>> Hi,
>>
>> I want to share this little issue I had while implementing an external
>> select webserver.
>> Case: daemon configured with MHD_USE_EPOLL_LINUX_ONLY plus EXTERNAL_SELECT.
>>
>> The typical example for the external select is:
>>
>> MHD_start_daemon (epoll)
>> while (1)
>> {
>> MHD_get_fdset (...)
>> MHD_get_timeout(...)
>> select(fds, timeout)
>> MHD_run
>> }
>>
>> Well, the example worked as far as I noticed that timeout had value 0 (not
>> null), meaning not waiting at all. When I changed it to NULL then the
>> example stopped working, because the program got blocked in the select
>> statement not being notified of incoming connections.
>> The problem is, MHD_start_daemon, creates the epollFD before the
>> listen-socket is set up. So, get_fdset returns a well epoll-fd without any
>> listen socket attached just after start_daemon returns.
>>
>> The solution for this is very simple, call MHD_run one time after the daemon
>> is started and before the select-loop:
>>
>> MHD_start_daemon (epoll)
>> MHD_run // => The listen socket is attached to the epollFD
>> while (1)
>> {select/run}
>>
>>
>> Thanks for your work!
>> ____________
>> Verificada la ausencia de virus por G Data MailSecurity
>>
>> Versión: AVA 24.2721 del 18.06.2014
>> Noticias de virus: www.antiviruslab.com
>>
>
> ____________
> Verificada la ausencia de virus por G Data MailSecurity
>
> Versión: AVA 24.2736 del 19.06.2014
> Noticias de virus: www.antiviruslab.com
>