View Issue Details

IDProjectCategoryView StatusLast Update
0001662libmicrohttpdportabilitypublic2011-03-04 10:57
Reporterbplant Assigned ToChristian Grothoff  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version0.9.5 
Summary0001662: Shutdown server without killing threads
DescriptionThe current shutdown function kills all in progress connections. This is fine since a normal OS will free any held memory and/or locks. Other OS' (such an as RTOS) don't offer this feature and killing threads/tasks does not release memory and/or locks.

The attached patch provides the option to make the MHD_close_connections() function non-static so that a custom shutdown function can be implemented.
TagsNo tags attached.
Attached Files
mhd_ext_shutdown.patch (1,195 bytes)   
Index: D:/svn/dspy/NEW/libmicrohttpd/tags/0.9.5-r1/src/daemon/daemon.c
===================================================================
--- D:/svn/dspy/NEW/libmicrohttpd/tags/0.9.5-r1/src/daemon/daemon.c	(revision 694)
+++ D:/svn/dspy/NEW/libmicrohttpd/tags/0.9.5-r1/src/daemon/daemon.c	(revision 769)
@@ -2131,7 +2131,7 @@
 /**
  * Close all connections for the daemon
  */
-static void
+void
 MHD_close_connections (struct MHD_Daemon *daemon)
 {
   while (daemon->connections != NULL)
Index: D:/svn/dspy/NEW/libmicrohttpd/tags/0.9.5-r1/src/include/microhttpd.h
===================================================================
--- D:/svn/dspy/NEW/libmicrohttpd/tags/0.9.5-r1/src/include/microhttpd.h	(revision 694)
+++ D:/svn/dspy/NEW/libmicrohttpd/tags/0.9.5-r1/src/include/microhttpd.h	(revision 769)
@@ -1110,6 +1110,13 @@
 ssize_t send_param_adapter (struct MHD_Connection *connection,
 			const void *other, size_t i);
 #endif
+#ifdef MHD_ALLOW_EXTERNAL_STOP
+/**
+ * Close all connections for the daemon
+ */
+void
+MHD_close_connections (struct MHD_Daemon *daemon);
+#endif
 
 /* **************** Connection handling functions ***************** */
 
mhd_ext_shutdown.patch (1,195 bytes)   

Activities

root

2011-02-24 13:57

administrator   ~0004261

Eh, why don't you call 'MHD_stop_daemon'? That function DOES call 'MHD_close_connections'.

MHD *does* terminate all of its threads and closes all of its sockets and releases all of its memory/locks properly if 'MHD_close_connections' is called, so I really do not understand your problem.

bplant

2011-02-24 15:41

reporter   ~0004268

I did try calling MHD_stop_daemon. It was a race condition. From memory, I think it was the following:

1. main daemon thread calls select on daemon->socket_fd
2. select adds the calling thread to a queue and sleeps
3. MHD_stop_daemon calls close on daemon->socket_fd
4. MHD_stop_daemon kills the main daemon thread
5. The main daemon thread has not woken up yet and so the call to select never removed the main daemon thread from the queue.

I'm not suggesting for a second that there is anything wrong with MHD. This issue is caused by limitations of the RTOS and TCP/IP stack that I'm using. Unfortunately I can't run a fully fledged OS on a 80MHz MCU with 96KB of memory so I've got to work with what I have. Having the ability to write a custom stop function allows for these odd limitations to be worked around.

Christian Grothoff

2011-02-27 00:39

manager   ~0004269

You're wrong about step (4): MHD does never 'kill' the daemon thread, it just waits for it to terminate (normally!).

We use 'pthread_join' here, 'pthread_kill' is not killing the thread but merely sending it a signal asking it to wake up (not to die!).

Could you investigate some more as to what is actually going on?

bplant

2011-02-28 08:41

reporter   ~0004270

Hmmm, the platform I'm using doesn't have the concept of signals so pthread_kill is, well, killing. I'll look into what options I have. Thanks for the info. Feel free to close the bug.

Christian Grothoff

2011-02-28 13:50

manager   ~0004271

We can avoid the use of pthread_kill by using a pipe instead. Do you have pipes?

bplant

2011-02-28 14:12

reporter   ~0004274

I'm afraid not. The OS (freertos based) fits into 4-9KB of ROM so it doesn't do much other than provide multi-tasking, mutexes, semaphores and queues.

Christian Grothoff

2011-03-02 16:57

manager   ~0004275

So how do you get TCP!? Btw, switching to pipes (which I'm still thinking of doing) would also have advantages in terms of energy consumption (no more waking up from select if idle).

Christian Grothoff

2011-03-02 17:08

manager   ~0004277

Oh, and we'd not need a big pipe, just 1 byte to transmit via a selectable thingy to stop the select loop. So emulating it using a 1-byte-buffered TCP stream would also work.

bplant

2011-03-02 17:49

reporter   ~0004279

I have thread-safe queues and semaphores that can be used for thread synchronisation. I don't have conditional variables though (unlike pthread). A semaphore would seem to be much more lightweight than a TCP socket.

Christian Grothoff

2011-03-03 21:46

manager   ~0004282

But you cannot 'select' on a semaphore! What constructs do you have that you can 'select' on? I was suggesting a TCP socket because that way you at least don't have to add anything extra to the OS.

bplant

2011-03-03 22:40

reporter   ~0004283

Haha, the semaphores available to me take a timeout option similar to that of select. In my OS (freeRTOS), semaphores implemented using queues, so queues also take a timeout option.

Do you need to send a signal to the main select thread to wake it? The daemon checks daemon->shutdown every loop and the main select thread exits when it is set. select() will surely return almost immediately after the listening TCP socket is closed so the main select thread should wake and exit almost immediately without needing to send a signal using pthread_kill().

Christian Grothoff

2011-03-04 09:33

manager   ~0004285

Well, there was one case where this would have been nice: if you have a thread per connection, that thread would typically not notice the listen socket going away. But I can fix that by having those threads select on the listen socket as well (but not process the listen socket there). That leads to unnecessary wake-ups of those threads (on incoming connections, they may wake up needlessly), but otherwise similar to using a pipe (2 FDs in select/poll sets) and, no more need for pipes or signals.

bplant

2011-03-04 10:00

reporter   ~0004286

Select is already used in MHD_handle_connection which means the threads are already waking up periodically (every 1 second?). The while loop containing the select call appears to check con->daemon->shutdown so the per connection thread should already wake up, see that the daemon has been told to shutdown and then shut itself down if I'm not mistaken.

Christian Grothoff

2011-03-04 10:10

manager   ~0004287

pipe is now also gone, so this should now be fixed (SVN 14584). This version now uses neither signals nor pipes but just shutdown of the server socket to terminate all loops.

Issue History

Date Modified Username Field Change
2011-02-23 15:58 bplant New Issue
2011-02-23 15:58 bplant File Added: mhd_ext_shutdown.patch
2011-02-24 13:57 root Note Added: 0004261
2011-02-24 13:57 root Status new => feedback
2011-02-24 15:41 bplant Note Added: 0004268
2011-02-27 00:39 Christian Grothoff Note Added: 0004269
2011-02-28 08:41 bplant Note Added: 0004270
2011-02-28 13:50 Christian Grothoff Note Added: 0004271
2011-02-28 14:12 bplant Note Added: 0004274
2011-03-02 16:57 Christian Grothoff Note Added: 0004275
2011-03-02 17:08 Christian Grothoff Note Added: 0004277
2011-03-02 17:49 bplant Note Added: 0004279
2011-03-03 21:46 Christian Grothoff Note Added: 0004282
2011-03-03 22:40 bplant Note Added: 0004283
2011-03-04 09:33 Christian Grothoff Note Added: 0004285
2011-03-04 10:00 bplant Note Added: 0004286
2011-03-04 10:10 Christian Grothoff Note Added: 0004287
2011-03-04 10:10 Christian Grothoff Status feedback => resolved
2011-03-04 10:10 Christian Grothoff Resolution open => fixed
2011-03-04 10:10 Christian Grothoff Assigned To => Christian Grothoff
2011-03-04 10:57 Christian Grothoff Status resolved => closed