Fix segmentation fault when using jq in threads
In previous code nomem_handler in jv_alloc.c is called only once and therefore the structure is not initialized for second and following threads. This leads to segmentation fault in multi-threading environment. This patch moves initialization of nomem_handler out of the pthread_once call.
This commit is contained in:
1 parent
5300fbda58
commit
2dbae5610b
1 file changed
+26
-7
+26
-7
@@ -45,9 +45,11 @@ static void memory_exhausted() {
|
|||||||
#ifdef HAVE_PTHREAD_KEY_CREATE
|
#ifdef HAVE_PTHREAD_KEY_CREATE
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
pthread_key_t nomem_handler_key;
|
static pthread_key_t nomem_handler_key;
|
||||||
pthread_once_t mem_once = PTHREAD_ONCE_INIT;
|
static pthread_once_t mem_once = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
|
/* tsd_fini is called on application exit */
|
||||||
|
/* it clears the nomem_handler allocated in the main thread */
|
||||||
static void tsd_fini(void) {
|
static void tsd_fini(void) {
|
||||||
struct nomem_handler *nomem_handler;
|
struct nomem_handler *nomem_handler;
|
||||||
nomem_handler = pthread_getspecific(nomem_handler_key);
|
nomem_handler = pthread_getspecific(nomem_handler_key);
|
||||||
@@ -57,8 +59,15 @@ static void tsd_fini(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The tsd_fini_thread is a destructor set by calling */
|
||||||
|
/* pthread_key_create(&nomem_handler_key, tsd_fini_thread) */
|
||||||
|
/* It is called when thread ends */
|
||||||
|
static void tsd_fini_thread(void *nomem_handler) {
|
||||||
|
free(nomem_handler);
|
||||||
|
}
|
||||||
|
|
||||||
static void tsd_init(void) {
|
static void tsd_init(void) {
|
||||||
if (pthread_key_create(&nomem_handler_key, NULL) != 0) {
|
if (pthread_key_create(&nomem_handler_key, tsd_fini_thread) != 0) {
|
||||||
fprintf(stderr, "jq: error: cannot create thread specific key");
|
fprintf(stderr, "jq: error: cannot create thread specific key");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
@@ -66,15 +75,23 @@ static void tsd_init(void) {
|
|||||||
fprintf(stderr, "jq: error: cannot set an exit handler");
|
fprintf(stderr, "jq: error: cannot set an exit handler");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler));
|
}
|
||||||
if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {
|
|
||||||
fprintf(stderr, "jq: error: cannot set thread specific data");
|
static void tsd_init_nomem_handler(void)
|
||||||
abort();
|
{
|
||||||
|
if (pthread_getspecific(nomem_handler_key) == NULL) {
|
||||||
|
struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler));
|
||||||
|
if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {
|
||||||
|
fprintf(stderr, "jq: error: cannot set thread specific data");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
|
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
|
||||||
pthread_once(&mem_once, tsd_init); // cannot fail
|
pthread_once(&mem_once, tsd_init); // cannot fail
|
||||||
|
tsd_init_nomem_handler();
|
||||||
|
|
||||||
struct nomem_handler *nomem_handler;
|
struct nomem_handler *nomem_handler;
|
||||||
|
|
||||||
nomem_handler = pthread_getspecific(nomem_handler_key);
|
nomem_handler = pthread_getspecific(nomem_handler_key);
|
||||||
@@ -91,6 +108,8 @@ static void memory_exhausted() {
|
|||||||
struct nomem_handler *nomem_handler;
|
struct nomem_handler *nomem_handler;
|
||||||
|
|
||||||
pthread_once(&mem_once, tsd_init);
|
pthread_once(&mem_once, tsd_init);
|
||||||
|
tsd_init_nomem_handler();
|
||||||
|
|
||||||
nomem_handler = pthread_getspecific(nomem_handler_key);
|
nomem_handler = pthread_getspecific(nomem_handler_key);
|
||||||
if (nomem_handler)
|
if (nomem_handler)
|
||||||
nomem_handler->handler(nomem_handler->data); // Maybe handler() will longjmp() to safety
|
nomem_handler->handler(nomem_handler->data); // Maybe handler() will longjmp() to safety
|
||||||
|
|||||||
Reference in new issue
Block a user