Permalink
Browse files

beginnings of some debugging methods for #132

  • Loading branch information...
1 parent 977da57 commit 7a7c979766208ad19977031ccef06f27f558e5e2 @krakjoe committed Aug 6, 2013
Showing with 187 additions and 6 deletions.
  1. +35 −0 classes/stackable.h
  2. +37 −0 classes/thread.h
  3. +36 −0 classes/worker.h
  4. +1 −1 phpdoc/constants.xml
  5. +65 −5 src/object.c
  6. +13 −0 src/thread.h
View
@@ -22,6 +22,7 @@ PHP_METHOD(Stackable, notify);
PHP_METHOD(Stackable, isRunning);
PHP_METHOD(Stackable, isWaiting);
PHP_METHOD(Stackable, isTerminated);
+PHP_METHOD(Stackable, getTerminationInfo);
PHP_METHOD(Stackable, synchronized);
PHP_METHOD(Stackable, lock);
PHP_METHOD(Stackable, unlock);
@@ -44,6 +45,8 @@ ZEND_BEGIN_ARG_INFO_EX(Stackable_isWaiting, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(Stackable_isTerminated, 0, 0, 0)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(Stackable_getTerminationInfo, 0, 0, 0)
+ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(Stackable_synchronized, 0, 0, 1)
ZEND_ARG_INFO(0, function)
@@ -81,6 +84,7 @@ zend_function_entry pthreads_stackable_methods[] = {
PHP_ME(Stackable, isRunning, Stackable_isRunning, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Stackable, isWaiting, Stackable_isWaiting, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Stackable, isTerminated, Stackable_isTerminated, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+ PHP_ME(Stackable, getTerminationInfo, Stackable_getTerminationInfo, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Stackable, synchronized, Stackable_synchronized, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Stackable, lock, Stackable_lock, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Stackable, unlock, Stackable_unlock, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
@@ -151,6 +155,37 @@ PHP_METHOD(Stackable, isTerminated)
} else zend_error(E_ERROR, "pthreads has experienced an internal error while preparing to read the state of a %s and cannot continue", PTHREADS_NAME);
} /* }}} */
+/* {{{ proto boolean Stackable::getTerminationInfo()
+ Will return information concerning the location of the termination to aid debugging */
+PHP_METHOD(Stackable, getTerminationInfo)
+{
+ PTHREAD thread = PTHREADS_FETCH;
+
+ if (thread) {
+ if (pthreads_state_isset(thread->state, PTHREADS_ST_ERROR TSRMLS_CC)) {
+ array_init(return_value);
+
+ if (thread->error->clazz) {
+ add_assoc_string(
+ return_value, "scope", thread->error->clazz, 1);
+ }
+
+ if (thread->error->method) {
+ add_assoc_string(
+ return_value, "function", thread->error->method, 1);
+ }
+
+ if (thread->error->file) {
+ add_assoc_string(
+ return_value, "file", thread->error->file, 1);
+ add_assoc_long(return_value, "line", thread->error->line);
+ }
+ } else {
+ RETURN_FALSE;
+ }
+ } else zend_error(E_ERROR, "pthreads has experienced an internal error while preparing to read the state of a %s and cannot continue", PTHREADS_NAME);
+} /* }}} */
+
/* {{{ proto void Stackable::synchronized(Callable function, ...)
Will synchronize the object, call the function, passing anything after the function as parameters
*/
View
@@ -38,6 +38,8 @@ PHP_METHOD(Thread, shift);
PHP_METHOD(Thread, pop);
PHP_METHOD(Thread, chunk);
+PHP_METHOD(Thread, getTerminationInfo);
+
ZEND_BEGIN_ARG_INFO_EX(Thread_start, 0, 0, 0)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
@@ -76,6 +78,9 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(Thread_isTerminated, 0, 0, 0)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(Thread_getTerminationInfo, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(Thread_synchronized, 0, 0, 1)
ZEND_ARG_INFO(0, function)
ZEND_END_ARG_INFO()
@@ -116,6 +121,7 @@ zend_function_entry pthreads_thread_methods[] = {
PHP_ME(Thread, isJoined, Thread_isJoined, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Thread, isWaiting, Thread_isWaiting, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Thread, isTerminated, Thread_isTerminated, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+ PHP_ME(Thread, getTerminationInfo, Thread_getTerminationInfo, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Thread, getThreadId, Thread_getThreadId, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL|ZEND_ACC_STATIC)
PHP_ME(Thread, getCreatorId, Thread_getCreatorId, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Thread, synchronized, Thread_synchronized, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
@@ -231,6 +237,37 @@ PHP_METHOD(Thread, isTerminated)
} else zend_error(E_ERROR, "pthreads has experienced an internal error while preparing to read the state of a %s and cannot continue", PTHREADS_NAME);
} /* }}} */
+/* {{{ proto boolean Thread::getTerminationInfo()
+ Will return information concerning the location of the termination to aid debugging */
+PHP_METHOD(Thread, getTerminationInfo)
+{
+ PTHREAD thread = PTHREADS_FETCH;
+
+ if (thread) {
+ if (pthreads_state_isset(thread->state, PTHREADS_ST_ERROR TSRMLS_CC)) {
+ array_init(return_value);
+
+ if (thread->error->clazz) {
+ add_assoc_string(
+ return_value, "scope", thread->error->clazz, 1);
+ }
+
+ if (thread->error->method) {
+ add_assoc_string(
+ return_value, "function", thread->error->method, 1);
+ }
+
+ if (thread->error->file) {
+ add_assoc_string(
+ return_value, "file", thread->error->file, 1);
+ add_assoc_long(return_value, "line", thread->error->line);
+ }
+ } else {
+ RETURN_FALSE;
+ }
+ } else zend_error(E_ERROR, "pthreads has experienced an internal error while preparing to read the state of a %s and cannot continue", PTHREADS_NAME);
+} /* }}} */
+
/* {{{ proto boolean Thread::wait([long timeout])
Will cause the calling thread to wait for notification from the referenced object
When a timeout is used and reached boolean false will return
View
@@ -23,6 +23,7 @@ PHP_METHOD(Worker, isStarted);
PHP_METHOD(Worker, isShutdown);
PHP_METHOD(Worker, isWorking);
PHP_METHOD(Worker, isTerminated);
+PHP_METHOD(Worker, getTerminationInfo);
PHP_METHOD(Worker, stack);
PHP_METHOD(Worker, unstack);
PHP_METHOD(Worker, getStacked);
@@ -56,6 +57,9 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(Worker_isTerminated, 0, 0, 0)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(Worker_getTerminationInfo, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(Worker_stack, 0, 0, 1)
ZEND_ARG_INFO(0, work)
ZEND_END_ARG_INFO()
@@ -100,6 +104,7 @@ zend_function_entry pthreads_worker_methods[] = {
PHP_ME(Worker, isStarted, Worker_isStarted, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Worker, isWorking, Worker_isWorking, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Worker, isTerminated, Worker_isTerminated, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+ PHP_ME(Worker, getTerminationInfo, Worker_getTerminationInfo, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
PHP_ME(Worker, merge, Worker_merge, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
@@ -247,6 +252,37 @@ PHP_METHOD(Worker, isTerminated)
} else zend_error(E_ERROR, "pthreads has experienced an internal error while preparing to read the state of a %s and cannot continue", PTHREADS_NAME);
} /* }}} */
+/* {{{ proto boolean Worker::getTerminationInfo()
+ Will return information concerning the location of the termination to aid debugging */
+PHP_METHOD(Worker, getTerminationInfo)
+{
+ PTHREAD thread = PTHREADS_FETCH;
+
+ if (thread) {
+ if (pthreads_state_isset(thread->state, PTHREADS_ST_ERROR TSRMLS_CC)) {
+ array_init(return_value);
+
+ if (thread->error->clazz) {
+ add_assoc_string(
+ return_value, "scope", thread->error->clazz, 1);
+ }
+
+ if (thread->error->method) {
+ add_assoc_string(
+ return_value, "function", thread->error->method, 1);
+ }
+
+ if (thread->error->file) {
+ add_assoc_string(
+ return_value, "file", thread->error->file, 1);
+ add_assoc_long(return_value, "line", thread->error->line);
+ }
+ } else {
+ RETURN_FALSE;
+ }
+ } else zend_error(E_ERROR, "pthreads has experienced an internal error while preparing to read the state of a %s and cannot continue", PTHREADS_NAME);
+} /* }}} */
+
/* {{{ proto boolean Worker::shutdown()
Will wait for execution of all Stackables to complete before shutting down the Worker */
PHP_METHOD(Worker, shutdown)
View
@@ -72,7 +72,7 @@
</simpara>
</listitem>
</varlistentry>
- <varlistentry xml:id="constant.pthreads_inherit_all">
+ <varlistentry xml:id="constant.pthreads_inherit_none">
<term>
<constant>PTHREADS_INHERIT_NONE</constant>
(<type>integer</type>)
View
@@ -117,6 +117,56 @@ zend_bool pthreads_unset_state(PTHREAD thread, int mask TSRMLS_DC){
return result;
} /* }}} */
+/* {{{ save the current error for object */
+static inline void pthreads_error_save(PTHREAD thread TSRMLS_DC) {
+ if (EG(active_op_array)) {
+ /* deal with scope stuff */
+ {
+ zend_function *active = (zend_function*) EG(active_op_array);
+
+ if (active->common.scope) {
+ thread->error->clazz = strndup(active->common.scope->name, strlen(active->common.scope->name));
+ } else thread->error->clazz = NULL;
+
+ if (active->common.function_name) {
+ thread->error->method = strndup(active->common.function_name, strlen(active->common.function_name));
+ } else thread->error->method = NULL;
+ }
+
+ /* deal with file stuff */
+ {
+ const char *tmp;
+
+ tmp = zend_get_executed_filename(TSRMLS_C);
+ if (tmp)
+ thread->error->file = strndup(tmp, strlen(tmp));
+
+ thread->error->line = zend_get_executed_lineno(TSRMLS_C);
+ }
+ }
+} /* }}} */
+
+/* {{{ allocate error structure */
+static inline void pthreads_error_alloc(PTHREAD object) {
+ object->error = calloc(1, sizeof(*object->error));
+} /* }}} */
+
+/* {{{ free the error saved for object */
+static inline void pthreads_error_free(PTHREAD thread TSRMLS_DC) {
+ if (thread->error) {
+ if (thread->error->clazz)
+ free(thread->error->clazz);
+
+ if (thread->error->method)
+ free(thread->error->method);
+
+ if (thread->error->file)
+ free(thread->error->file);
+
+ free(thread->error);
+ }
+} /* }}} */
+
/* {{{ pop for php */
size_t pthreads_stack_pop(PTHREAD thread, PTHREAD work TSRMLS_DC) {
zend_bool locked;
@@ -336,7 +386,8 @@ static int pthreads_connect(PTHREAD source, PTHREAD destination TSRMLS_DC) {
pthreads_synchro_free(destination->synchro TSRMLS_CC);
pthreads_resources_free(destination->resources TSRMLS_CC);
pthreads_address_free(destination->address);
-
+ pthreads_error_free(destination TSRMLS_CC);
+
if (PTHREADS_IS_WORKER(destination)) {
zend_hash_destroy(
&destination->stack->objects
@@ -366,6 +417,7 @@ static int pthreads_connect(PTHREAD source, PTHREAD destination TSRMLS_DC) {
destination->modifiers = source->modifiers;
destination->store = source->store;
destination->stack = source->stack;
+ destination->error = source->error;
return SUCCESS;
} else return FAILURE;
@@ -379,7 +431,7 @@ static void pthreads_base_ctor(PTHREAD base, zend_class_entry *entry TSRMLS_DC)
{
zval *temp;
- zend_hash_copy(
+ zend_hash_copy(
base->std.properties,
&entry->default_properties,
(copy_ctor_func_t) zval_add_ref,
@@ -390,7 +442,6 @@ static void pthreads_base_ctor(PTHREAD base, zend_class_entry *entry TSRMLS_DC)
object_properties_init(&(base->std), entry);
#endif
-
base->cls = tsrm_ls;
base->address = pthreads_address_alloc(base);
base->options = PTHREADS_INHERIT_ALL;
@@ -405,7 +456,7 @@ static void pthreads_base_ctor(PTHREAD base, zend_class_entry *entry TSRMLS_DC)
base->modifiers = pthreads_modifiers_alloc(TSRMLS_C);
base->store = pthreads_store_alloc(TSRMLS_C);
base->resources = pthreads_resources_alloc(TSRMLS_C);
-
+
pthreads_modifiers_init(base->modifiers, entry TSRMLS_CC);
if (PTHREADS_IS_WORKER(base)) {
base->stack = (pthreads_stack) calloc(1, sizeof(*base->stack));
@@ -415,6 +466,8 @@ static void pthreads_base_ctor(PTHREAD base, zend_class_entry *entry TSRMLS_DC)
base->stack->position = 0L;
}
}
+
+ pthreads_error_alloc(base);
}
}
} /* }}} */
@@ -438,14 +491,16 @@ static void pthreads_base_dtor(void *arg TSRMLS_DC) {
pthreads_synchro_free(base->synchro TSRMLS_CC);
pthreads_resources_free(base->resources TSRMLS_CC);
pthreads_address_free(base->address);
-
+
if (PTHREADS_IS_WORKER(base)) {
zend_hash_destroy(
&base->stack->objects
);
free(base->stack);
}
}
+
+ pthreads_error_free(base TSRMLS_CC);
#if PHP_VERSION_ID > 50399
{
@@ -734,6 +789,11 @@ static void * pthreads_routine(void *arg) {
if (terminated) {
pthreads_state_set(
current->state, PTHREADS_ST_ERROR TSRMLS_CC);
+ /* save error information */
+ pthreads_error_save(current TSRMLS_CC);
+
+ php_printf("Thread Exited %s::%s in %s on line %lu\n",
+ current->error->clazz, current->error->method, current->error->file, current->error->line);
}
/* unset running for waiters */
View
@@ -54,6 +54,14 @@ typedef struct _pthreads_address {
size_t length;
} *pthreads_address; /* }}} */
+/* {{{ error structure */
+typedef struct _pthreads_error {
+ unsigned char *file;
+ unsigned char *clazz;
+ unsigned char *method;
+ uint line;
+} *pthreads_error; /* }}} */
+
/* {{{ thread structure */
typedef struct _pthread_construct {
/*
@@ -127,6 +135,11 @@ typedef struct _pthread_construct {
* Thread Address
*/
pthreads_address address;
+
+ /*
+ * Threading Error
+ */
+ pthreads_error error;
/**
* Shared Resources

0 comments on commit 7a7c979

Please sign in to comment.