View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0001690 | libmicrohttpd | thread pool | public | 2011-06-14 08:44 | 2011-07-07 23:30 |
| Reporter | bplant | Assigned To | Christian Grothoff | ||
| Priority | normal | Severity | feature | Reproducibility | N/A |
| Status | closed | Resolution | won't fix | ||
| Product Version | 0.9.5 | ||||
| Summary | 0001690: Queue new connections when max connection limit is reached | ||||
| Description | I am using MHD in thread-per-connection mode on an embedded processor than has only 96KB of ram. As such, I cannot create many threads and therefore cannot set MHD's connection limit very high. The problem I'm finding is that web browsers send off lots of parallel requests to the web server (fetching images, javascript and css files) which is causing the maximum connection limit to be reached randomly. Currently when the connection limit is reached, the connection is closed. It would be better if the connection was instead queued and serviced when an in progress connection finished. As a *rough* proof of concept, I am checking daemon->max_connections at the start of MHD_accept_connection(). If daemon->max_connections == 0, I'm sleeping for 100ms and returning MHD_NO. This is allowing me to run MHD with a max connection limit of only 3. | ||||
| Tags | No tags attached. | ||||
|
|
Actually, this should not be a big issue since there is an OS mechanism for this that MHD is using: the listen queue. If MHD has too many connections, it stops *accepting* connections from the listen socket (at least that's what should happen by design, not sure it has been tested well). The OS then queues the connections, until the threshold given to the "listen" call is exceeded. MHD defaults to 5 here, but you can change this by passing a pre-initialized listen socket to the daemon start call. |
|
|
The behaviour that you describe is what I'm looking for. Unfortunately, it's not currently happening. The connection is getting closed in MHD_add_connection() if ((daemon->max_connections == 0) || (MHD_ip_limit_add (daemon, addr, addrlen) == MHD_NO)) { /* above connection limit - reject */ #if HAVE_MESSAGES MHD_DLOG (daemon, "Server reached connection limit (closing inbound connection)\n"); #endif SHUTDOWN (client_socket, SHUT_RDWR); CLOSE (client_socket); return MHD_NO; } It looks like connections would be queued when *not* operating in MHD_USE_THREAD_PER_CONNECTION: if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) { /* single-threaded, go over everything */ if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max)) return MHD_NO; /* If we're at the connection limit, no need to accept new connections. */ if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) ) FD_CLR(daemon->socket_fd, &rs); } else { /* accept only, have one thread per connection */ max = daemon->socket_fd; if (max == -1) return MHD_NO; FD_SET (max, &rs); } |
|
|
Ah, yes. Well, the MHD_ip_limit-check we cannot do until after we've accepted, so that one will need to stay anyway. In the MHD_USE_THREAD_PER_CONNECTION case, yes, that's an issue since it will be a bit tricky to wake up the master thread upon the termination of "any" of the client connections. I think the way to do it with 'poll' would be for the master thread to 'poll' on *all* client FDs (for SIGHUP-only). However, for 'select', I cannot think of a good solution (that wouldn't introduce something like pipes, which are again problematic on your platform). What prevents you from using the internal/external-select modes instead of thread-per-connection? That would save you the stack space for the threads AND elimiante this problem... |
|
|
Which mode would you recommend? The web server needs to be able to handle more than one connection at a time. I.e. It still needs to be able to handle connections if a client is downloading a large file. |
|
|
You may be able to handle 100s of parallel connections with 'external select' mode -- and you won't even need threads. I generally would recommend to people to start with 'external select' just because it avoid threads altogether. Then move from select to poll if you have trouble (and poll is available on your platform). Overall, on small embedded systems I don't really think any of the threaded modes make any sense --- for performance, they are really only for systems with many cores. |
|
|
I'm marking this as "won't fix" for now, given that I don't have a solution that would not introduce additional problems and have high complexity AND that I believe that there is a feasible alternative. This does not mean that given the right argument / patch, I could not be convinced otherwise. |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2011-06-14 08:44 | bplant | New Issue | |
| 2011-06-17 11:33 | Christian Grothoff | Note Added: 0004406 | |
| 2011-06-17 11:33 | Christian Grothoff | Status | new => feedback |
| 2011-06-17 12:03 | bplant | Note Added: 0004418 | |
| 2011-06-22 10:54 | Christian Grothoff | Note Added: 0004449 | |
| 2011-06-23 09:58 | bplant | Note Added: 0004454 | |
| 2011-06-23 11:25 | Christian Grothoff | Note Added: 0004455 | |
| 2011-07-07 23:30 | Christian Grothoff | Note Added: 0004486 | |
| 2011-07-07 23:30 | Christian Grothoff | Assigned To | => Christian Grothoff |
| 2011-07-07 23:30 | Christian Grothoff | Reproducibility | always => N/A |
| 2011-07-07 23:30 | Christian Grothoff | Status | feedback => closed |
| 2011-07-07 23:30 | Christian Grothoff | Resolution | open => won't fix |
| 2011-07-07 23:30 | Christian Grothoff | Category | other => multi-threaded operation |
| 2013-05-06 12:53 | Christian Grothoff | Category | multi-threaded operation => libmicrohttpd multi-threaded operation |
| 2024-01-21 13:25 | Christian Grothoff | Category | libmicrohttpd multi-threaded operation => thread pool |