daemon.c

Go to the documentation of this file.
00001 /*
00002      This file is part of libmicrohttpd
00003      (C) 2007 Daniel Pittman and Christian Grothoff
00004 
00005      This library is free software; you can redistribute it and/or
00006      modify it under the terms of the GNU Lesser General Public
00007      License as published by the Free Software Foundation; either
00008      version 2.1 of the License, or (at your option) any later version.
00009 
00010      This library is distributed in the hope that it will be useful,
00011      but WITHOUT ANY WARRANTY; without even the implied warranty of
00012      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013      Lesser General Public License for more details.
00014 
00015      You should have received a copy of the GNU Lesser General Public
00016      License along with this library; if not, write to the Free Software
00017      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 */
00020 
00028 #include "internal.h"
00029 #include "response.h"
00030 #include "connection.h"
00031 #include "memorypool.h"
00032 
00036 #define MHD_MAX_CONNECTIONS_DEFAULT FD_SETSIZE -4
00037 
00041 #define MHD_POOL_SIZE_DEFAULT (1024 * 1024)
00042 
00047 #define DEBUG_CLOSE MHD_NO
00048 
00053 #define DEBUG_CONNECT MHD_NO
00054 
00055 
00063 int
00064 MHD_get_fdset (struct MHD_Daemon *daemon,
00065                fd_set * read_fd_set,
00066                fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd)
00067 {
00068   struct MHD_Connection *pos;
00069   int fd;
00070 
00071   if ((daemon == NULL) ||
00072       (read_fd_set == NULL) ||
00073       (write_fd_set == NULL) ||
00074       (except_fd_set == NULL) ||
00075       (max_fd == NULL) ||
00076       (-1 == (fd = daemon->socket_fd)) ||
00077       (daemon->shutdown == MHD_YES) ||
00078       ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0))
00079     return MHD_NO;
00080   FD_SET (fd, read_fd_set);
00081   if ((*max_fd) < fd)
00082     *max_fd = fd;
00083   pos = daemon->connections;
00084   while (pos != NULL)
00085     {
00086       if (MHD_YES != MHD_connection_get_fdset (pos,
00087                                                read_fd_set,
00088                                                write_fd_set,
00089                                                except_fd_set, max_fd))
00090         return MHD_NO;
00091       pos = pos->next;
00092     }
00093 #if DEBUG_CONNECT
00094   MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd);
00095 #endif
00096   return MHD_YES;
00097 }
00098 
00103 static void *
00104 MHD_handle_connection (void *data)
00105 {
00106   struct MHD_Connection *con = data;
00107   int num_ready;
00108   fd_set rs;
00109   fd_set ws;
00110   fd_set es;
00111   int max;
00112   struct timeval tv;
00113   unsigned int timeout;
00114   unsigned int now;
00115 
00116   if (con == NULL)
00117     abort ();
00118   timeout = con->daemon->connection_timeout;
00119   while ((!con->daemon->shutdown) && (con->socket_fd != -1))
00120     {
00121       FD_ZERO (&rs);
00122       FD_ZERO (&ws);
00123       FD_ZERO (&es);
00124       max = 0;
00125       MHD_connection_get_fdset (con, &rs, &ws, &es, &max);
00126       now = time (NULL);
00127       tv.tv_usec = 0;
00128       if (timeout > (now - con->last_activity))
00129         tv.tv_sec = timeout - (now - con->last_activity);
00130       else
00131         tv.tv_sec = 0;
00132       num_ready = SELECT (max + 1,
00133                           &rs, &ws, &es, (timeout != 0) ? &tv : NULL);
00134       if (num_ready < 0)
00135         {
00136           if (errno == EINTR)
00137             continue;
00138 #if HAVE_MESSAGES
00139           MHD_DLOG (con->daemon, "Error during select (%d): `%s'\n",
00140                     max, STRERROR (errno));
00141 #endif
00142           break;
00143         }
00144       if (FD_ISSET (con->socket_fd, &rs))
00145         MHD_connection_handle_read (con);
00146       if ((con->socket_fd != -1) && (FD_ISSET (con->socket_fd, &ws)))
00147         MHD_connection_handle_write (con);
00148       if (con->socket_fd != -1)
00149         MHD_connection_handle_idle (con);
00150     }
00151   if (con->socket_fd != -1)
00152     {
00153 #if DEBUG_CLOSE
00154 #if HAVE_MESSAGES
00155       MHD_DLOG (con->daemon,
00156                 "Processing thread terminating, closing connection\n");
00157 #endif
00158 #endif
00159       SHUTDOWN (con->socket_fd, SHUT_RDWR);
00160       CLOSE (con->socket_fd);
00161       con->socket_fd = -1;
00162     }
00163   return NULL;
00164 }
00165 
00166 
00172 static int
00173 MHD_accept_connection (struct MHD_Daemon *daemon)
00174 {
00175   struct MHD_Connection *pos;
00176   struct MHD_Connection *connection;
00177   struct sockaddr_in6 addr6;
00178   struct sockaddr *addr = (struct sockaddr *) &addr6;
00179   socklen_t addrlen;
00180   unsigned int have;
00181   int s;
00182 #if OSX
00183   static int on = 1;
00184 #endif
00185 
00186 
00187   if (sizeof (struct sockaddr) > sizeof (struct sockaddr_in6))
00188     abort ();                   /* fatal, serious error */
00189   addrlen = sizeof (struct sockaddr_in6);
00190   memset (addr, 0, sizeof (struct sockaddr_in6));
00191   s = ACCEPT (daemon->socket_fd, addr, &addrlen);
00192   if ((s < 0) || (addrlen <= 0))
00193     {
00194 #if HAVE_MESSAGES
00195       MHD_DLOG (daemon, "Error accepting connection: %s\n", STRERROR (errno));
00196 #endif
00197       if (s != -1)
00198         {
00199           SHUTDOWN (s, SHUT_RDWR);
00200           CLOSE (s);            /* just in case */
00201         }
00202       return MHD_NO;
00203     }
00204 #if DEBUG_CONNECT
00205   MHD_DLOG (daemon, "Accepted connection on socket %d\n", s);
00206 #endif
00207   have = 0;
00208   if ((daemon->per_ip_connection_limit != 0) && (daemon->max_connections > 0))
00209     {
00210       pos = daemon->connections;
00211       while (pos != NULL)
00212         {
00213           if ((pos->addr != NULL) && (pos->addr_len == addrlen))
00214             {
00215               if (addrlen == sizeof (struct sockaddr_in))
00216                 {
00217                   const struct sockaddr_in *a1 =
00218                     (const struct sockaddr_in *) &addr;
00219                   const struct sockaddr_in *a2 =
00220                     (const struct sockaddr_in *) pos->addr;
00221                   if (0 ==
00222                       memcmp (&a1->sin_addr, &a2->sin_addr,
00223                               sizeof (struct in_addr)))
00224                     have++;
00225                 }
00226               if (addrlen == sizeof (struct sockaddr_in6))
00227                 {
00228                   const struct sockaddr_in6 *a1 =
00229                     (const struct sockaddr_in6 *) &addr;
00230                   const struct sockaddr_in6 *a2 =
00231                     (const struct sockaddr_in6 *) pos->addr;
00232                   if (0 ==
00233                       memcmp (&a1->sin6_addr, &a2->sin6_addr,
00234                               sizeof (struct in6_addr)))
00235                     have++;
00236                 }
00237             }
00238           pos = pos->next;
00239         }
00240     }
00241 
00242   if ((daemon->max_connections == 0) ||
00243       ((daemon->per_ip_connection_limit != 0) &&
00244        (daemon->per_ip_connection_limit <= have)))
00245     {
00246       /* above connection limit - reject */
00247 #if HAVE_MESSAGES
00248       MHD_DLOG (daemon,
00249                 "Server reached connection limit (closing inbound connection)\n");
00250 #endif
00251       SHUTDOWN (s, SHUT_RDWR);
00252       CLOSE (s);
00253       return MHD_NO;
00254     }
00255   if ((daemon->apc != NULL) &&
00256       (MHD_NO == daemon->apc (daemon->apc_cls, addr, addrlen)))
00257     {
00258 #if DEBUG_CLOSE
00259 #if HAVE_MESSAGES
00260       MHD_DLOG (daemon, "Connection rejected, closing connection\n");
00261 #endif
00262 #endif
00263       SHUTDOWN (s, SHUT_RDWR);
00264       CLOSE (s);
00265       return MHD_YES;
00266     }
00267 #if OSX
00268 #ifdef SOL_SOCKET
00269 #ifdef SO_NOSIGPIPE
00270   setsockopt (s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof (on));
00271 #endif
00272 #endif
00273 #endif
00274   connection = malloc (sizeof (struct MHD_Connection));
00275   if (connection == NULL)
00276     {
00277 #if HAVE_MESSAGES
00278       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00279 #endif
00280       SHUTDOWN (s, SHUT_RDWR);
00281       CLOSE (s);
00282       return MHD_NO;
00283     }
00284   memset (connection, 0, sizeof (struct MHD_Connection));
00285   connection->pool = NULL;
00286   connection->addr = malloc (addrlen);
00287   if (connection->addr == NULL)
00288     {
00289 #if HAVE_MESSAGES
00290       MHD_DLOG (daemon, "Error allocating memory: %s\n", STRERROR (errno));
00291 #endif
00292       SHUTDOWN (s, SHUT_RDWR);
00293       CLOSE (s);
00294       free (connection);
00295       return MHD_NO;
00296     }
00297   memcpy (connection->addr, addr, addrlen);
00298   connection->addr_len = addrlen;
00299   connection->socket_fd = s;
00300   connection->daemon = daemon;
00301   if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
00302       (0 != pthread_create (&connection->pid,
00303                             NULL, &MHD_handle_connection, connection)))
00304     {
00305 #if HAVE_MESSAGES
00306       MHD_DLOG (daemon, "Failed to create a thread: %s\n", STRERROR (errno));
00307 #endif
00308       SHUTDOWN (s, SHUT_RDWR);
00309       CLOSE (s);
00310       free (connection->addr);
00311       free (connection);
00312       return MHD_NO;
00313     }
00314   connection->last_activity = time (NULL);
00315   connection->next = daemon->connections;
00316   daemon->connections = connection;
00317   daemon->max_connections--;
00318   return MHD_YES;
00319 }
00320 
00321 
00327 static void
00328 MHD_cleanup_connections (struct MHD_Daemon *daemon)
00329 {
00330   struct MHD_Connection *pos;
00331   struct MHD_Connection *prev;
00332   void *unused;
00333 
00334   pos = daemon->connections;
00335   prev = NULL;
00336   while (pos != NULL)
00337     {
00338       if (pos->socket_fd == -1)
00339         {
00340           if (prev == NULL)
00341             daemon->connections = pos->next;
00342           else
00343             prev->next = pos->next;
00344           if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00345             {
00346               pthread_kill (pos->pid, SIGALRM);
00347               pthread_join (pos->pid, &unused);
00348             }
00349           MHD_destroy_response (pos->response);
00350           MHD_pool_destroy (pos->pool);
00351           free (pos->addr);
00352           free (pos);
00353           daemon->max_connections++;
00354           if (prev == NULL)
00355             pos = daemon->connections;
00356           else
00357             pos = prev->next;
00358           continue;
00359         }
00360       prev = pos;
00361       pos = pos->next;
00362     }
00363 }
00364 
00376 int
00377 MHD_get_timeout (struct MHD_Daemon *daemon, unsigned long long *timeout)
00378 {
00379   time_t earliest_deadline;
00380   time_t now;
00381   struct MHD_Connection *pos;
00382   unsigned int dto;
00383 
00384   dto = daemon->connection_timeout;
00385   if (0 == dto)
00386     return MHD_NO;
00387   pos = daemon->connections;
00388   if (pos == NULL)
00389     return MHD_NO;              /* no connections */
00390   now = time (NULL);
00391   /* start with conservative estimate */
00392   earliest_deadline = now + dto;
00393   while (pos != NULL)
00394     {
00395       if (earliest_deadline > pos->last_activity + dto)
00396         earliest_deadline = pos->last_activity + dto;
00397       pos = pos->next;
00398     }
00399   if (earliest_deadline < now)
00400     *timeout = 0;
00401   else
00402     *timeout = (earliest_deadline - now);
00403   return MHD_YES;
00404 }
00405 
00412 static int
00413 MHD_select (struct MHD_Daemon *daemon, int may_block)
00414 {
00415   struct MHD_Connection *pos;
00416   int num_ready;
00417   fd_set rs;
00418   fd_set ws;
00419   fd_set es;
00420   int max;
00421   struct timeval timeout;
00422   unsigned long long ltimeout;
00423   int ds;
00424   time_t now;
00425 
00426   timeout.tv_sec = 0;
00427   timeout.tv_usec = 0;
00428   if (daemon == NULL)
00429     abort ();
00430   if (daemon->shutdown == MHD_YES)
00431     return MHD_NO;
00432   FD_ZERO (&rs);
00433   FD_ZERO (&ws);
00434   FD_ZERO (&es);
00435   max = 0;
00436 
00437   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00438     {
00439       /* single-threaded, go over everything */
00440       if (MHD_NO == MHD_get_fdset (daemon, &rs, &ws, &es, &max))
00441         return MHD_NO;
00442     }
00443   else
00444     {
00445       /* accept only, have one thread per connection */
00446       max = daemon->socket_fd;
00447       if (max == -1)
00448         return MHD_NO;
00449       FD_SET (max, &rs);
00450     }
00451   if (may_block == MHD_NO)
00452     {
00453       timeout.tv_usec = 0;
00454       timeout.tv_sec = 0;
00455     }
00456   else
00457     {
00458       /* ltimeout is in ms */
00459       if (MHD_YES == MHD_get_timeout (daemon, &ltimeout))
00460         {
00461           timeout.tv_usec = (ltimeout % 1000) * 1000;
00462           timeout.tv_sec = ltimeout / 1000;
00463           may_block = MHD_NO;
00464         }
00465     }
00466   num_ready = SELECT (max + 1,
00467                       &rs, &ws, &es, may_block == MHD_NO ? &timeout : NULL);
00468   if (daemon->shutdown == MHD_YES)
00469     return MHD_NO;
00470   if (num_ready < 0)
00471     {
00472       if (errno == EINTR)
00473         return MHD_YES;
00474 #if HAVE_MESSAGES
00475       MHD_DLOG (daemon, "Select failed: %s\n", STRERROR (errno));
00476 #endif
00477       return MHD_NO;
00478     }
00479   ds = daemon->socket_fd;
00480   if (ds == -1)
00481     return MHD_YES;
00482   if (FD_ISSET (ds, &rs))
00483     MHD_accept_connection (daemon);
00484   if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
00485     {
00486       /* do not have a thread per connection, process all connections now */
00487       now = time (NULL);
00488       pos = daemon->connections;
00489       while (pos != NULL)
00490         {
00491           ds = pos->socket_fd;
00492           if (ds != -1)
00493             {
00494               if (FD_ISSET (ds, &rs))
00495                 MHD_connection_handle_read (pos);
00496               if ((pos->socket_fd != -1) && (FD_ISSET (ds, &ws)))
00497                 MHD_connection_handle_write (pos);
00498               if (pos->socket_fd != -1)
00499                 MHD_connection_handle_idle (pos);
00500             }
00501           pos = pos->next;
00502         }
00503     }
00504   return MHD_YES;
00505 }
00506 
00507 
00518 int
00519 MHD_run (struct MHD_Daemon *daemon)
00520 {
00521   if ((daemon->shutdown != MHD_NO) ||
00522       (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
00523       (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
00524     return MHD_NO;
00525   MHD_select (daemon, MHD_NO);
00526   MHD_cleanup_connections (daemon);
00527   return MHD_YES;
00528 }
00529 
00530 
00535 static void *
00536 MHD_select_thread (void *cls)
00537 {
00538   struct MHD_Daemon *daemon = cls;
00539   while (daemon->shutdown == MHD_NO)
00540     {
00541       MHD_select (daemon, MHD_YES);
00542       MHD_cleanup_connections (daemon);
00543     }
00544   return NULL;
00545 }
00546 
00547 
00559 struct MHD_Daemon *
00560 MHD_start_daemon (unsigned int options,
00561                   unsigned short port,
00562                   MHD_AcceptPolicyCallback apc,
00563                   void *apc_cls,
00564                   MHD_AccessHandlerCallback dh, void *dh_cls, ...)
00565 {
00566   const int on = 1;
00567   struct MHD_Daemon *retVal;
00568   int socket_fd;
00569   struct sockaddr_in servaddr4;
00570   struct sockaddr_in6 servaddr6;
00571   const struct sockaddr *servaddr;
00572   socklen_t addrlen;
00573   va_list ap;
00574   enum MHD_OPTION opt;
00575 
00576   if ((options & MHD_USE_SSL) != 0)
00577     return NULL;
00578   if ((port == 0) || (dh == NULL))
00579     return NULL;
00580   if ((options & MHD_USE_IPv6) != 0)
00581     socket_fd = SOCKET (PF_INET6, SOCK_STREAM, 0);
00582   else
00583     socket_fd = SOCKET (PF_INET, SOCK_STREAM, 0);
00584   if (socket_fd < 0)
00585     {
00586 #if HAVE_MESSAGES
00587       if ((options & MHD_USE_DEBUG) != 0)
00588         fprintf (stderr, "Call to socket failed: %s\n", STRERROR (errno));
00589 #endif
00590       return NULL;
00591     }
00592   if ((SETSOCKOPT (socket_fd,
00593                    SOL_SOCKET,
00594                    SO_REUSEADDR,
00595                    &on, sizeof (on)) < 0) && (options & MHD_USE_DEBUG) != 0)
00596     {
00597 #if HAVE_MESSAGES
00598       fprintf (stderr, "setsockopt failed: %s\n", STRERROR (errno));
00599 #endif
00600     }
00601   if ((options & MHD_USE_IPv6) != 0)
00602     {
00603       memset (&servaddr6, 0, sizeof (struct sockaddr_in6));
00604       servaddr6.sin6_family = AF_INET6;
00605       servaddr6.sin6_port = htons (port);
00606       servaddr = (struct sockaddr *) &servaddr6;
00607       addrlen = sizeof (struct sockaddr_in6);
00608     }
00609   else
00610     {
00611       memset (&servaddr4, 0, sizeof (struct sockaddr_in));
00612       servaddr4.sin_family = AF_INET;
00613       servaddr4.sin_port = htons (port);
00614       servaddr = (struct sockaddr *) &servaddr4;
00615       addrlen = sizeof (struct sockaddr_in);
00616     }
00617   if (BIND (socket_fd, servaddr, addrlen) < 0)
00618     {
00619 #if HAVE_MESSAGES
00620       if ((options & MHD_USE_DEBUG) != 0)
00621         fprintf (stderr,
00622                  "Failed to bind to port %u: %s\n", port, STRERROR (errno));
00623 #endif
00624       CLOSE (socket_fd);
00625       return NULL;
00626     }
00627   if (LISTEN (socket_fd, 20) < 0)
00628     {
00629 #if HAVE_MESSAGES
00630       if ((options & MHD_USE_DEBUG) != 0)
00631         fprintf (stderr,
00632                  "Failed to listen for connections: %s\n", STRERROR (errno));
00633 #endif
00634       CLOSE (socket_fd);
00635       return NULL;
00636     }
00637   retVal = malloc (sizeof (struct MHD_Daemon));
00638   if (retVal == NULL)
00639     {
00640       CLOSE (socket_fd);
00641       return NULL;
00642     }
00643   memset (retVal, 0, sizeof (struct MHD_Daemon));
00644   retVal->options = options;
00645   retVal->port = port;
00646   retVal->apc = apc;
00647   retVal->apc_cls = apc_cls;
00648   retVal->socket_fd = socket_fd;
00649   retVal->default_handler = dh;
00650   retVal->default_handler_cls = dh_cls;
00651   retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT;
00652   retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
00653   retVal->connection_timeout = 0;       /* no timeout */
00654   va_start (ap, dh_cls);
00655   while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION)))
00656     {
00657       switch (opt)
00658         {
00659         case MHD_OPTION_CONNECTION_MEMORY_LIMIT:
00660           retVal->pool_size = va_arg (ap, unsigned int);
00661           break;
00662         case MHD_OPTION_CONNECTION_LIMIT:
00663           retVal->max_connections = va_arg (ap, unsigned int);
00664           break;
00665         case MHD_OPTION_CONNECTION_TIMEOUT:
00666           retVal->connection_timeout = va_arg (ap, unsigned int);
00667           break;
00668         case MHD_OPTION_NOTIFY_COMPLETED:
00669           retVal->notify_completed =
00670             va_arg (ap, MHD_RequestCompletedCallback);
00671           retVal->notify_completed_cls = va_arg (ap, void *);
00672           break;
00673         case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
00674           retVal->per_ip_connection_limit = va_arg (ap, unsigned int);
00675           break;
00676         default:
00677 #if HAVE_MESSAGES
00678           fprintf (stderr,
00679                    "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n");
00680 #endif
00681           abort ();
00682         }
00683     }
00684   va_end (ap);
00685   if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) ||
00686        (0 != (options & MHD_USE_SELECT_INTERNALLY))) &&
00687       (0 != pthread_create (&retVal->pid, NULL, &MHD_select_thread, retVal)))
00688     {
00689 #if HAVE_MESSAGES
00690       MHD_DLOG (retVal,
00691                 "Failed to create listen thread: %s\n", STRERROR (errno));
00692 #endif
00693       free (retVal);
00694       CLOSE (socket_fd);
00695       return NULL;
00696     }
00697   return retVal;
00698 }
00699 
00703 void
00704 MHD_stop_daemon (struct MHD_Daemon *daemon)
00705 {
00706   void *unused;
00707   int fd;
00708 
00709   if (daemon == NULL)
00710     return;
00711   daemon->shutdown = MHD_YES;
00712   fd = daemon->socket_fd;
00713   daemon->socket_fd = -1;
00714 #if DEBUG_CLOSE
00715 #if HAVE_MESSAGES
00716   MHD_DLOG (daemon, "MHD shutdown, closing listen socket\n");
00717 #endif
00718 #endif
00719   CLOSE (fd);
00720   if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
00721       (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)))
00722     {
00723       pthread_kill (daemon->pid, SIGALRM);
00724       pthread_join (daemon->pid, &unused);
00725     }
00726   while (daemon->connections != NULL)
00727     {
00728       if (-1 != daemon->connections->socket_fd)
00729         {
00730 #if DEBUG_CLOSE
00731 #if HAVE_MESSAGES
00732           MHD_DLOG (daemon, "MHD shutdown, closing active connections\n");
00733 #endif
00734 #endif
00735           if (daemon->notify_completed != NULL)
00736             daemon->notify_completed (daemon->notify_completed_cls,
00737                                       daemon->connections,
00738                                       &daemon->connections->client_context,
00739                                       MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
00740           SHUTDOWN (daemon->connections->socket_fd, SHUT_RDWR);
00741           CLOSE (daemon->connections->socket_fd);
00742           daemon->connections->socket_fd = -1;
00743         }
00744       MHD_cleanup_connections (daemon);
00745     }
00746   free (daemon);
00747 }
00748 
00749 #ifndef WINDOWS
00750 
00751 static struct sigaction sig;
00752 
00753 static struct sigaction old;
00754 
00755 static void
00756 sigalrmHandler (int sig)
00757 {
00758 }
00759 
00763 void __attribute__ ((constructor)) MHD_pthread_handlers_ltdl_init ()
00764 {
00765   /* make sure SIGALRM does not kill us */
00766   memset (&sig, 0, sizeof (struct sigaction));
00767   memset (&old, 0, sizeof (struct sigaction));
00768   sig.sa_flags = SA_NODEFER;
00769   sig.sa_handler = &sigalrmHandler;
00770   sigaction (SIGALRM, &sig, &old);
00771 }
00772 
00773 void __attribute__ ((destructor)) MHD_pthread_handlers_ltdl_fini ()
00774 {
00775   sigaction (SIGALRM, &old, &sig);
00776 }
00777 #else
00778 void __attribute__ ((constructor)) MHD_win_ltdl_init ()
00779 {
00780   plibc_init ("CRISP", "libmicrohttpd");
00781 }
00782 
00783 void __attribute__ ((destructor)) MHD_win_ltdl_fini ()
00784 {
00785   plibc_shutdown ();
00786 }
00787 #endif
00788 
00789 /* end of daemon.c */

Generated on Sat Jan 10 03:18:34 2009 for GNU libmicrohttpd by  doxygen 1.5.7.1