commit e095054e7700817a9467d70b38e5763b629c9bc6
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri May 6 10:55:41 2011 +0200
prepare to fix a GC/thread-related bug: no semantic change
* rest.c (gc_register_thread): Add a comment.
We must arrange to call GC_unregister_my_thread upon return
from any thread that calls gc_register_thread. The two affected
functions have many return points, so the clean/reliable way is
to wrap them and perform thread registration/unregistration from
each wrapper. Here we simply create the wrapper functions:
(prov_list_generator_0): Rename from prov_list_generator.
(prov_list_generator): Define as a trivial wrapper around the above.
(access_handler_0): Rename from access_handler.
(access_handler): Define as a trivial wrapper around the above.
rest.c | 33 +++++++++++++++++++++++++++++----
1 files changed, 29 insertions(+), 4 deletions(-)
---
diff --git a/rest.c b/rest.c
index 0ec6a0f..c3a22ed 100644
--- a/rest.c
+++ b/rest.c
@@ -76,6 +76,14 @@ enum { POST_BUF_SIZE = 4096 };
the callback function (i.e., I/O buffer size). */
enum { CB_BLOCK_SIZE = 64 * 1024 };
+/* Whenever a thread is created via a 3rd-party library, we must
+ register it with GC before it can allocate garbage collected memory,
+ or assign pointers to the garbage collected heap.
+ For example, the microhttpd library creates threads running
+ our prov_list_generator and access_handler functions.
+ Thus, each of those must use this macro.
+ WARNING: whenever you use this macro, you must also arrange
+ to call GC_unregister_my_thread upon thread completion. */
#define gc_register_thread() \
{ \
struct GC_stack_base gc_stack_base; \
@@ -1691,7 +1699,7 @@ prov_name_compare (const void *av, const void *bv)
}
static ssize_t
-prov_list_generator (void *ctx, uint64_t pos, char *buf, size_t max)
+prov_list_generator_0 (void *ctx, uint64_t pos, char *buf, size_t max)
{
gc_register_thread();
my_state *ms = ctx;
@@ -1766,6 +1774,13 @@ prov_list_generator (void *ctx, uint64_t pos, char *buf, size_t
max)
}
}
+static ssize_t
+prov_list_generator (void *ctx, uint64_t pos, char *buf, size_t max)
+{
+ int ret = prov_list_generator_0 (ctx, pos, buf, max);
+ return ret;
+}
+
static int
proxy_list_provs (void *cctx, struct MHD_Connection *conn, const char *url,
const char *method, const char *version, const char *data,
@@ -2166,9 +2181,9 @@ parse_url (const char *url, my_state *ms)
}
static int
-access_handler (void *cctx, struct MHD_Connection *conn, const char *url,
- const char *method, const char *version, const char *data,
- size_t *data_size, void **rctx)
+access_handler_0 (void *cctx, struct MHD_Connection *conn, const char *url,
+ const char *method, const char *version, const char *data,
+ size_t *data_size, void **rctx)
{
unsigned int i;
url_type utype;
@@ -2225,6 +2240,16 @@ access_handler (void *cctx, struct MHD_Connection *conn, const char
*url,
return MHD_YES;
}
+static int
+access_handler (void *cctx, struct MHD_Connection *conn, const char *url,
+ const char *method, const char *version, const char *data,
+ size_t *data_size, void **rctx)
+{
+ int ret = access_handler_0 (cctx, conn, url, method, version,
+ data, data_size, rctx);
+ return ret;
+}
+
/* These enum values cannot possibly conflict with the option values
ordinarily used by commands, including CHAR_MAX + 1, etc. Avoid
CHAR_MIN - 1, as it may equal -1, the getopt end-of-options value. */