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:
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
*/