[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [libmicrohttpd] Suspending/resuming not working with external select
From: |
Christian Grothoff |
Subject: |
Re: [libmicrohttpd] Suspending/resuming not working with external select |
Date: |
Mon, 5 Sep 2016 13:45:46 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.6.0 |
Dear Johannes,
Calling "resume_suspended_connections()" within MHD_get_fdset() would
not suffice. If we do that, we would put the connections back into
"normal processing" mode, but the subsequent select() by the application
would still block (until the next incoming connection).
Only by calling "MHD_run()" we're able to immediately resume full
processing (i.e. call the applications' handler for the connection)
instead of blocking on something.
Sure, we might be 'tricky' and remember the resume event and put a
timeout of zero on the select(). Still, that then just is exactly
equivalent to executing "MHD_run()" (which is MHD_get_fdset(), select()
with timeout of 0 plus MHD_run_from_select()), so your performance
argument wouldn't hold here either. Now, note that for a quick hack, I
put the "MHD_run()" in your code immediately after the resume call.
However, as the resume was done in a loop, it would be fine to do it
after that loop (i.e. you could set a local variable to indicate if the
loop did end up resuming anything, and then call MHD_run() once after
_all_ of the resumed connections).
As for your epoll()-comment, I'm a bit confused as you should never call
MHD_run_from_select() when you are using MHD_USE_EPOLL. If you use
MHD_USE_EPOLL(), you should simply call MHD_run() which will internally
call epoll(). While you may use 'select()' on the EPOLL_FD MHD gives
you, but then you should still call MHD_run() and not MHD_run_from_select().
I hope this clarifies.
Happy hacking!
Christian
On 09/05/2016 03:20 AM, Johannes Spangenberg wrote:
> Thank you, Christian.
>
> Your fix did work for me. In my small example, and in my other program,
> too. I already discovered that I missed FD_ZERO and max=0 but since it
> did not fix the bug, I have not send a mail about it. I wrote that the
> second request was never accepted. After reading your mail, I figured
> out that it is not true for curl. Firefox simply did not send the second
> request. Maybe firefox has tied to reuse the connection or it did
> combine both request for the same resource.
>
> As a feature request: I would suggest that MHD_get_fdset() calls
> resume_suspended_connections(). Then, it could do the work which is
> necessary to get the right fd_sets. It looks a little bit strange to me
> that I have to call MHD_run() with all it's overhead of calling select()
> and handling requests. This way, the application would also not need to
> track it's calls to MHD_resume_connection() to know whether it has to
> call this function. Another possibility would be a new function that can
> be called before calling MHD_get_fdset(). Another problem of the current
> implementation is that MHD_run_from_select() does never call
> resume_suspended_connections() while using epoll when there is no IO
> activity. The reason is that the function is called in MHD_epoll() which
> is not called without IO activity. I think the API could be improved
> there if it is not to difficult to implement.
>
> Again, thank you for your help.
> Johannes
>
>
> Am 04.09.2016 um 17:53 schrieb Christian Grothoff:
>> Dear Johannes,
>>
>> You need to run "MHD_run()" between resuming and asking for the FD set.
>> It was not very well documented, so I've fixed the documentation in SVN
>> 37877.
>>
>> You also didn't FD_ZERO your fdsets, but that's minor. I've attached
>> your code with my changes, so that it works.
>>
>> Happy hacking!
>>
>> Christian
>>
>> On 09/04/2016 03:49 PM, Johannes Spangenberg wrote:
>>> Hello,
>>>
>>> I encountered some problems while using the libmicrohttpd. I was using
>>> MHD_suspend_connection() and MHD_resume_connection() in combination with
>>> an external event loop. The problem was that the connection was not
>>> resumed until another request was made. I checked the event loop but
>>> they was running and calling MHD_run_with_select() periodically.
>>> Afterwards, I wrote a small test program, attached to this mail, to
>>> check if it is a bug or misunderstanding of the library. I also tested
>>> it agains the last version (0.9.51).
>>>
>>> Connections are still not resumed in the small test program. But in
>>> difference to my original project, receiving another request does not
>>> resume the first connection. The second request is never accepted by
>>> libmicrohttpd. It seems that select() does not return to acceppt the
>>> second connection after calling MHD_suspend_connection() on the first
>>> one. If I'm not calling MHD_suspend_connection() and
>>> MHD_resume_connection(), everythink works. Futuremore, if I am using
>>> MHD_USE_SELECT_INTERNALLY and replace the external loop with a busy
>>> loop, everything works as well. I thinks it looks like there is a bug in
>>> MHD_suspend_connection() and MHD_resume_connection() when used with
>>> external select. Could someone take a look and check whether I'm doing
>>> something wrong or there is a bug in the library.
>>>
>>> I searchd for it but could not find a solution to fix it. A found
>>> another conversation in the mailing list: [MHD_suspend_connection
>>> API](http://lists.gnu.org/archive/html/libmicrohttpd/2014-02/msg00005.html).
>>> It is not clear but thing it may be possible that he stumbled over the
>>> same bug.
>>>
>>> My english is not the best but I hope you can understand everything.
>>> Johannes
>>>
>
0xE29FC3CC.asc
Description: application/pgp-keys
signature.asc
Description: OpenPGP digital signature