summaryrefslogtreecommitdiff
path: root/TSRM
diff options
context:
space:
mode:
Diffstat (limited to 'TSRM')
-rw-r--r--TSRM/TSRM.c31
-rw-r--r--TSRM/TSRM.h2
2 files changed, 29 insertions, 4 deletions
diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c
index 6669df6d43..2c7a40a2de 100644
--- a/TSRM/TSRM.c
+++ b/TSRM/TSRM.c
@@ -55,8 +55,9 @@ static int resource_types_table_size;
static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
/* New thread handlers */
-static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler;
-static tsrm_thread_end_func_t tsrm_new_thread_end_handler;
+static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler = NULL;
+static tsrm_thread_end_func_t tsrm_new_thread_end_handler = NULL;
+static tsrm_shutdown_func_t tsrm_shutdown_handler = NULL;
/* Debug support */
int tsrm_error(int level, const char *format, ...);
@@ -120,6 +121,8 @@ static int32 tls_key;
# warning tsrm_set_interpreter_context is probably broken on this platform
#endif
+TSRM_TLS uint8_t in_main_thread = 0;
+
/* Startup TSRM (call once for the entire process) */
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
{
@@ -136,6 +139,9 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
tls_key = tls_allocate();
#endif
+ /* ensure singleton */
+ in_main_thread = 1;
+
tsrm_error_file = stderr;
tsrm_error_set(debug_level, debug_filename);
tsrm_tls_table_size = expected_threads;
@@ -158,8 +164,6 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
tsmm_mutex = tsrm_mutex_alloc();
- tsrm_new_thread_begin_handler = tsrm_new_thread_end_handler = NULL;
-
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Started up TSRM, %d expected threads, %d expected resources", expected_threads, expected_resources));
return 1;
}
@@ -170,6 +174,11 @@ TSRM_API void tsrm_shutdown(void)
{
int i;
+ if (!in_main_thread) {
+ /* ensure singleton */
+ return;
+ }
+
if (tsrm_tls_table) {
for (i=0; i<tsrm_tls_table_size; i++) {
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
@@ -212,6 +221,12 @@ TSRM_API void tsrm_shutdown(void)
#elif defined(TSRM_WIN32)
TlsFree(tls_key);
#endif
+ if (tsrm_shutdown_handler) {
+ tsrm_shutdown_handler();
+ }
+ tsrm_new_thread_begin_handler = NULL;
+ tsrm_new_thread_end_handler = NULL;
+ tsrm_shutdown_handler = NULL;
}
@@ -740,6 +755,14 @@ TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread
}
+TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler)
+{
+ void *retval = (void *) tsrm_shutdown_handler;
+
+ tsrm_shutdown_handler = shutdown_handler;
+ return retval;
+}
+
/*
* Debug support
diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h
index f9bb241050..2ffcbfee76 100644
--- a/TSRM/TSRM.h
+++ b/TSRM/TSRM.h
@@ -128,6 +128,7 @@ TSRM_API void ts_free_id(ts_rsrc_id id);
typedef void (*tsrm_thread_begin_func_t)(THREAD_T thread_id);
typedef void (*tsrm_thread_end_func_t)(THREAD_T thread_id);
+typedef void (*tsrm_shutdown_func_t)(void);
TSRM_API int tsrm_error(int level, const char *format, ...);
@@ -145,6 +146,7 @@ TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset);
TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler);
TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler);
+TSRM_API void *tsrm_set_shutdown_handler(tsrm_shutdown_func_t shutdown_handler);
/* these 3 APIs should only be used by people that fully understand the threading model
* used by PHP/Zend and the selected SAPI. */