libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit c3b093d70af180a2e0c6c2473dc02854351c8616
parent a952ad938c6ede2cbb537e7181ac5f0ff643828c
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu, 12 Nov 2009 15:27:11 +0000

cleaning up and documenting panic callback

Diffstat:
MChangeLog | 5+++++
Mdoc/microhttpd.texi | 10++++++++++
Msrc/daemon/connection.c | 16++++++++++++++--
Msrc/daemon/daemon.c | 60++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/daemon/internal.h | 2+-
Msrc/include/microhttpd.h | 12+++++++++++-
6 files changed, 83 insertions(+), 22 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,8 @@ +Thu Nov 12 16:19:14 CET 2009 + Adding support for setting a custom error handler for + fatal errors (previously, the implementation always + called 'abort' in these cases). -CG/ND + Wed Nov 11 12:54:16 CET 2009 Adding support for poll (alternative to select allowing for more than FD_SETSIZE parallel connections). -JM diff --git a/doc/microhttpd.texi b/doc/microhttpd.texi @@ -778,6 +778,16 @@ iteration. @node microhttpd-init @chapter Starting and stopping the server +@deftypefun {void} MHD_set_panic_func (MHD_PanicCallback cb, void *cls) +Set a handler for fatal errors. + +@table @var +@item cb +function to call if MHD encounteres a fatal internal error. If no handler was set explicitly, MHD will call @code{abort}. + +@item cls +closure argument for cb; the other arguments are the name of the source file, line number and a string describing the nature of the fatal error (which can be NULL) +@end table @deftypefun {struct MHD_Daemon *} MHD_start_daemon (unsigned int flags, unsigned short port, MHD_AcceptPolicyCallback apc, void *apc_cls, MHD_AccessHandlerCallback dh, void *dh_cls, ...) Start a webserver on the given port. diff --git a/src/daemon/connection.c b/src/daemon/connection.c @@ -341,7 +341,13 @@ try_ready_normal_body (struct MHD_Connection *connection) connection->response_write_position)); if ((ret == 0) && (0 != (connection->daemon->options & MHD_USE_SELECT_INTERNALLY))) - mhd_panic (mhd_panic_cls, __FILE__, __LINE__, "API violation"); + mhd_panic (mhd_panic_cls, __FILE__, __LINE__, +#if HAVE_MESSAGES + "API violation" +#else + NULL +#endif + ); if (ret == -1) { /* either error or http 1.0 transfer, close @@ -1283,7 +1289,13 @@ call_connection_handler (struct MHD_Connection *connection) return; } if (processed > used) - mhd_panic (mhd_panic_cls, __FILE__, __LINE__, "API violation"); + mhd_panic (mhd_panic_cls, __FILE__, __LINE__, +#if HAVE_MESSAGES + "API violation" +#else + NULL +#endif + ); if (processed != 0) instant_retry = MHD_NO; /* client did not process everything */ used -= processed; diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c @@ -80,15 +80,24 @@ static void pthread_kill (int, int) { /** * Default implementation of the panic function */ -void mhd_panic_std(void *cls, - const char *file, - unsigned int line, - const char *reason) +static void +mhd_panic_std(void *cls, + const char *file, + unsigned int line, + const char *reason) { abort (); } + +/** + * Handler for fatal errors. + */ MHD_PanicCallback mhd_panic; + +/** + * Closure argument for "mhd_panic". + */ void *mhd_panic_cls; /** @@ -483,8 +492,6 @@ MHD_handle_connection (void *data) struct MHD_Pollfd mp; struct pollfd p; - if (con == NULL) - mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); timeout = con->daemon->connection_timeout; while ((!con->daemon->shutdown) && (con->socket_fd != -1)) { now = time (NULL); @@ -636,10 +643,6 @@ MHD_accept_connection (struct MHD_Daemon *daemon) static int on = 1; #endif -#if HAVE_INET6 - if (sizeof (struct sockaddr) > sizeof (struct sockaddr_in6)) - mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); /* fatal, serious error */ -#endif addrlen = sizeof (addrstorage); memset (addr, 0, sizeof (addrstorage)); @@ -773,7 +776,19 @@ MHD_accept_connection (struct MHD_Daemon *daemon) "Failed to setup TLS credentials: unknown credential type %d\n", connection->daemon->cred_type); #endif - mhd_panic (mhd_panic_cls, __FILE__, __LINE__, "Unknown credential type"); + SHUTDOWN (s, SHUT_RDWR); + CLOSE (s); + MHD_ip_limit_del (daemon, addr, addrlen); + free (connection->addr); + free (connection); + mhd_panic (mhd_panic_cls, __FILE__, __LINE__, +#if HAVE_MESSAGES + "Unknown credential type" +#else + NULL +#endif + ); + return MHD_NO; } MHD__gnutls_transport_set_ptr (connection->tls_session, (MHD_gnutls_transport_ptr_t) connection); @@ -932,8 +947,6 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) timeout.tv_sec = 0; timeout.tv_usec = 0; - if (daemon == NULL) - mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); if (daemon->shutdown == MHD_YES) return MHD_NO; FD_ZERO (&rs); @@ -1186,7 +1199,7 @@ MHD_start_daemon_va (unsigned int options, #if HAVE_MESSAGES MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n"); #endif - abort(); + mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); } MHD__gnutls_global_init (); if (0 != pthread_mutex_unlock (&MHD_gnutls_init_mutex)) @@ -1194,7 +1207,7 @@ MHD_start_daemon_va (unsigned int options, #if HAVE_MESSAGES MHD_DLOG (retVal, "Failed to release gnutls mutex\n"); #endif - abort(); + mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); } /* set default priorities */ MHD_tls_set_default_priority (&retVal->priority_cache, "", NULL); @@ -1276,7 +1289,8 @@ MHD_start_daemon_va (unsigned int options, opt); } #endif - mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); + free (retVal); + return NULL; } } @@ -1712,7 +1726,17 @@ MHD_get_daemon_info (struct MHD_Daemon *daemon, } /** - * Sets the global error handler to a different implementation + * Sets the global error handler to a different implementation. "cb" + * will only be called in the case of typically fatal, serious + * internal consistency issues. These issues should only arise in the + * case of serious memory corruption or similar problems with the + * architecture. While "cb" is allowed to return and MHD will then + * try to continue, this is never safe. + * + * The default implementation that is used if no panic function is set + * simply calls "abort". Alternative implementations might call + * "exit" or other similar functions. + * * @param cb new error handler * @param cls passed to error handler */ @@ -1759,7 +1783,7 @@ sigalrmHandler (int sig) */ void ATTRIBUTE_CONSTRUCTOR MHD_init () { - mhd_panic = mhd_panic_std; + mhd_panic = &mhd_panic_std; mhd_panic_cls = NULL; #ifndef WINDOWS diff --git a/src/daemon/internal.h b/src/daemon/internal.h @@ -46,7 +46,7 @@ #define MHD_BUF_INC_SIZE 2048 /** - * Error handler + * Handler for fatal errors. */ extern MHD_PanicCallback mhd_panic; diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -972,7 +972,17 @@ MHD_set_connection_value (struct MHD_Connection *connection, const char *key, const char *value); /** - * Sets the global error handler to a different implementation + * Sets the global error handler to a different implementation. "cb" + * will only be called in the case of typically fatal, serious + * internal consistency issues. These issues should only arise in the + * case of serious memory corruption or similar problems with the + * architecture. While "cb" is allowed to return and MHD will then + * try to continue, this is never safe. + * + * The default implementation that is used if no panic function is set + * simply calls "abort". Alternative implementations might call + * "exit" or other similar functions. + * * @param cb new error handler * @param cls passed to error handler */