> > Date: Wed, 07 May 2014 14:24:40 +0200 > From: Christian Grothoff <[email protected]> > To: [email protected] > Subject: Re: [libmicrohttpd] Stuck Single Threaded > Message-ID: <[email protected]> > Content-Type: text/plain; charset="utf-8" > > On 05/05/2014 10:10 PM, Kenneth Mastro wrote: > > First, great library! Thanks for creating it! > > > > Using microhttpd, I created a reasonably well performing webserver for > > an embedded system I'm working on. Everything has been going well, but > > I'm stuck on something. > > > > I've been trying to add a 'Comet' feature to the library where > > long-polling can be done. In short, during the default URI handler > > callback (provided as args 5&6 to the start_daemon setup call), I > > ultimately 'wait' for the server to produce a message to send back to > > the client. I.e., the long-poll. If there are no messages after a > > while (e.g., a minute), I return an empty message back to the client and > > force it to ask again. > > > > The problem I'm having is that this seems to prevent the daemon from > > processing any other incoming connections - regardless of my threading > > model. I had assumed that 'select + thread pool' or 'one thread per > > connection' would allow what I'm doing to work, but it doesn't - it just > > sits and waits for the long-poll to time out (or send a valid message) > > before servicing the next client request. > > > > This isn't the behavior I expected - particularly for the 'one thread > > per connection' mode. > > > > Should I be doing this a different way? I don't quite see how, but is > > this main callback the wrong place to do something like this? Is my > > webserver structurally flawed in that I generate the content in that > > callback thread, in general? > > > > As a side note, I haven't played with the 'suspend/resume' option, yet - > > but it seems like that shouldn't be necessary (or valid/appropriate) for > > 'one thread per connection' mode. > > > > In short - how should I use the library to hold onto a request for an > > extended period of time as it prepares an answer while still allowing it > > to service other requests? > > That is usually not an issue; however, if you set a limit on the > number of parallel connections MHD is allowed to serve, then 'holding' > one request may prevent MHD from accepting additional requests. So > check that you didn't limit the requests (overall) or by IP address. > > Note that you can do long polling even with the other threading modes, > but those might be more complicated to use (you'll need to use stuff > like MHD_connection_suspend and returning '0' from the content reader > callback. > > As to the structure of your webserver, MHD deliberately offers you > various ways to generate the reply and organize your web server; > using the thread-per-connection method is not the most scalable > method, but not per-se bad --- I don't know your application, so > I cannot say if your webserver is 'flawed'. What I can say is that > yes, you should be able to do a 'Comet' feature this way with MHD in > principle. > > > I hope this helps! > > Happy hacking! > > Christian >
Thanks, Christian. I was able to get long-polling working. The problem was in my testing methodology (see my message from a couple hours ago). MHD is indeed flexible with regards to request processing - that's one of the reasons I thought I was doing something wrong. :) Another question, though, since you brought it up. My preferred threading mode is select (or maybe epoll, since I'm on Linux - haven't tried it yet) with a thread-pool. My past development experience leads me to assume that is the best combination of efficiency and performance, in general. I haven't seen any problems with doing it this way, but I'm not using the suspend/resume stuff. However - Your message implies there could be complications if I go that route. Should I use the built-in suspend/resume stuff even if I'm using a thread pool, or is it ok to just pause one of the MHD threads for the long-poll? Seems like it should be fine unless there's something funky about those threads or their management. I'm sure I could save some memory and task switching by suspending/resuming, but I don't think it's worth the extra complication if there isn't some inherent problem with the way I'm doing it. I don't have to worry much about the number of simultaneous users - I'm putting a cap on it at 10 users, with a maximum of 1 long-poll each, and I've set aside 20 threads in the pool. Should be more than enough. Memory use is not a big concern as long as it's not obscene. Thanks again for such a great library! Ken
