* replaced __thread with pthread_key_t/pthread_setspecific
* use pthread_once to initialize the request handler
This commit is contained in:
+35
-16
@@ -27,6 +27,7 @@
|
|||||||
#include <library.h>
|
#include <library.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
#include <ClearSilver/ClearSilver.h>
|
#include <ClearSilver/ClearSilver.h>
|
||||||
|
|
||||||
typedef struct private_request_t private_request_t;
|
typedef struct private_request_t private_request_t;
|
||||||
@@ -58,22 +59,28 @@ struct private_request_t {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* thread specific FCGX_Request, used for ClearSilver cgiwrap callbacks.
|
* key to a thread specific FCGX_Request, used for ClearSilver cgiwrap callbacks.
|
||||||
* ClearSilver cgiwrap is not threadsave, so we use a private
|
* ClearSilver cgiwrap is not threadsave, so we use a private
|
||||||
* context for each thread.
|
* context for each thread.
|
||||||
*/
|
*/
|
||||||
static __thread FCGX_Request *req;
|
static pthread_key_t req_key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* length of param list in req->envp
|
* length of param list in req->envp
|
||||||
*/
|
*/
|
||||||
static __thread int req_env_len;
|
static pthread_key_t req_env_len_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* control variable for pthread_once
|
||||||
|
*/
|
||||||
|
pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fcgiwrap read callback
|
* fcgiwrap read callback
|
||||||
*/
|
*/
|
||||||
static int read_cb(void *null, char *buf, int size)
|
static int read_cb(void *null, char *buf, int size)
|
||||||
{
|
{
|
||||||
|
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
|
||||||
return FCGX_GetStr(buf, size, req->in);
|
return FCGX_GetStr(buf, size, req->in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,6 +89,7 @@ static int read_cb(void *null, char *buf, int size)
|
|||||||
*/
|
*/
|
||||||
static int writef_cb(void *null, const char *format, va_list args)
|
static int writef_cb(void *null, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
|
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
|
||||||
FCGX_VFPrintF(req->out, format, args);
|
FCGX_VFPrintF(req->out, format, args);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -90,6 +98,7 @@ static int writef_cb(void *null, const char *format, va_list args)
|
|||||||
*/
|
*/
|
||||||
static int write_cb(void *null, const char *buf, int size)
|
static int write_cb(void *null, const char *buf, int size)
|
||||||
{
|
{
|
||||||
|
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
|
||||||
return FCGX_PutStr(buf, size, req->out);
|
return FCGX_PutStr(buf, size, req->out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +108,7 @@ static int write_cb(void *null, const char *buf, int size)
|
|||||||
static char *getenv_cb(void *null, const char *key)
|
static char *getenv_cb(void *null, const char *key)
|
||||||
{
|
{
|
||||||
char *value;
|
char *value;
|
||||||
|
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
|
||||||
value = FCGX_GetParam(key, req->envp);
|
value = FCGX_GetParam(key, req->envp);
|
||||||
return value ? strdup(value) : NULL;
|
return value ? strdup(value) : NULL;
|
||||||
}
|
}
|
||||||
@@ -120,7 +129,8 @@ static int iterenv_cb(void *null, int num, char **key, char **value)
|
|||||||
{
|
{
|
||||||
*key = NULL;
|
*key = NULL;
|
||||||
*value = NULL;
|
*value = NULL;
|
||||||
|
FCGX_Request *req = (FCGX_Request*)pthread_getspecific(req_key);
|
||||||
|
int req_env_len = (int)pthread_getspecific(req_env_len_key);
|
||||||
if (num < req_env_len)
|
if (num < req_env_len)
|
||||||
{
|
{
|
||||||
char *eq;
|
char *eq;
|
||||||
@@ -256,13 +266,24 @@ static void destroy(private_request_t *this)
|
|||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This initialization method is guaranteed to run only once
|
||||||
|
* for all threads.
|
||||||
|
*/
|
||||||
|
static void init(void)
|
||||||
|
{
|
||||||
|
cgiwrap_init_emu(NULL, read_cb, writef_cb, write_cb,
|
||||||
|
getenv_cb, putenv_cb, iterenv_cb);
|
||||||
|
pthread_key_create(&req_key, NULL);
|
||||||
|
pthread_key_create(&req_env_len_key, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* see header file
|
* see header file
|
||||||
*/
|
*/
|
||||||
request_t *request_create(FCGX_Request *request, bool debug)
|
request_t *request_create(FCGX_Request *request, bool debug)
|
||||||
{
|
{
|
||||||
NEOERR* err;
|
NEOERR* err;
|
||||||
static bool initialized = FALSE;
|
|
||||||
private_request_t *this = malloc_thing(private_request_t);
|
private_request_t *this = malloc_thing(private_request_t);
|
||||||
|
|
||||||
this->public.get_path = (char*(*)(request_t*))get_path;
|
this->public.get_path = (char*(*)(request_t*))get_path;
|
||||||
@@ -277,21 +298,19 @@ request_t *request_create(FCGX_Request *request, bool debug)
|
|||||||
this->public.setf = (void(*)(request_t*, char *format, ...))setf;
|
this->public.setf = (void(*)(request_t*, char *format, ...))setf;
|
||||||
this->public.destroy = (void(*)(request_t*))destroy;
|
this->public.destroy = (void(*)(request_t*))destroy;
|
||||||
|
|
||||||
if (!initialized)
|
pthread_once(&once, init);
|
||||||
{
|
|
||||||
cgiwrap_init_emu(NULL, read_cb, writef_cb, write_cb,
|
|
||||||
getenv_cb, putenv_cb, iterenv_cb);
|
|
||||||
initialized = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->req = request;
|
this->req = request;
|
||||||
req = request;
|
pthread_setspecific(req_key, (void*)request);
|
||||||
req_env_len = 0;
|
|
||||||
while (req->envp[req_env_len] != NULL)
|
int req_env_len = 0;
|
||||||
|
while (request->envp[req_env_len] != NULL)
|
||||||
{
|
{
|
||||||
req_env_len++;
|
req_env_len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_setspecific(req_env_len_key, (void*)req_env_len);
|
||||||
|
|
||||||
err = hdf_init(&this->hdf);
|
err = hdf_init(&this->hdf);
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user