Esempio n. 1
0
/* {{{ mysqlnd_res_meta::func_leave */
static enum_func_status
MYSQLND_METHOD(mysqlnd_debug, func_leave)(MYSQLND_DEBUG * self, unsigned int line,
										  const char * const file)
{
	char *func_name;
#ifdef MYSQLND_THREADED
	MYSQLND_ZTS(self);
#endif
	if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
		return PASS;
	}
#ifdef MYSQLND_THREADED
	if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
		return PASS; /* don't trace background threads */
	}
#endif
	if (zend_stack_count(&self->call_stack) >= self->nest_level_limit) {
		return PASS;
	}

	zend_stack_top(&self->call_stack, (void **)&func_name);

	if (func_name[0] == '\0') {
		; /* don't log that function */
	} else if (!zend_hash_num_elements(&self->not_filtered_functions) ||
		1 == zend_hash_exists(&self->not_filtered_functions, func_name, strlen(func_name) + 1))
	{
		self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, "<%s", func_name);
	}

	return zend_stack_del_top(&self->call_stack) == SUCCESS? PASS:FAIL;
}
Esempio n. 2
0
/* fetches the requested resource for the current thread */
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id)
{/*{{{*/
	THREAD_T thread_id;
	int hash_value;
	tsrm_tls_entry *thread_resources;

	if (!th_id) {
		/* Fast path for looking up the resources for the current
		 * thread. Its used by just about every call to
		 * ts_resource_ex(). This avoids the need for a mutex lock
		 * and our hashtable lookup.
		 */
		thread_resources = tsrm_tls_get();

		if (thread_resources) {
			TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for current thread %d", id, (long) thread_resources->thread_id));
			/* Read a specific resource from the thread's resources.
			 * This is called outside of a mutex, so have to be aware about external
			 * changes to the structure as we read it.
			 */
			TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
		}
		thread_id = tsrm_thread_id();
	} else {
		thread_id = *th_id;
	}

	TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for thread %ld", id, (long) thread_id));
	tsrm_mutex_lock(tsmm_mutex);

	hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
	thread_resources = tsrm_tls_table[hash_value];

	if (!thread_resources) {
		allocate_new_resource(&tsrm_tls_table[hash_value], thread_id);
		return ts_resource_ex(id, &thread_id);
	} else {
		 do {
			if (thread_resources->thread_id == thread_id) {
				break;
			}
			if (thread_resources->next) {
				thread_resources = thread_resources->next;
			} else {
				allocate_new_resource(&thread_resources->next, thread_id);
				return ts_resource_ex(id, &thread_id);
				/*
				 * thread_resources = thread_resources->next;
				 * break;
				 */
			}
		 } while (thread_resources);
	}
	tsrm_mutex_unlock(tsmm_mutex);
	/* Read a specific resource from the thread's resources.
	 * This is called outside of a mutex, so have to be aware about external
	 * changes to the structure as we read it.
	 */
	TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
}/*}}}*/
Esempio n. 3
0
/*
  Unlock a mutex.
  A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
{
	TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex unlocked thread: %ld", tsrm_thread_id()));
#ifdef TSRM_WIN32
	LeaveCriticalSection(mutexp);
	return 0;
#elif defined(GNUPTH)
	if (pth_mutex_release(mutexp)) {
		return 0;
	}
	return -1;
#elif defined(PTHREADS)
	return pthread_mutex_unlock(mutexp);
#elif defined(NSAPI)
	crit_exit(mutexp);
	return 0;
#elif defined(PI3WEB)
	return PISync_unlock(mutexp);
#elif defined(TSRM_ST)
	return st_mutex_unlock(mutexp);
#elif defined(BETHREADS)
	if (atomic_add(&mutexp->ben, -1) != 1)
		return release_sem(mutexp->sem);
	return 0;
#endif
}
Esempio n. 4
0
/*
  Lock a mutex.
  A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
{
	TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex locked thread: %ld", tsrm_thread_id()));
#ifdef TSRM_WIN32
	EnterCriticalSection(mutexp);
	return 0;
#elif defined(GNUPTH)
	if (pth_mutex_acquire(mutexp, 0, NULL)) {
		return 0;
	}
	return -1;
#elif defined(PTHREADS)
	return pthread_mutex_lock(mutexp);
#elif defined(NSAPI)
	crit_enter(mutexp);
	return 0;
#elif defined(PI3WEB)
	return PISync_lock(mutexp);
#elif defined(TSRM_ST)
	return st_mutex_lock(mutexp);
#elif defined(BETHREADS)
	if (atomic_add(&mutexp->ben, 1) != 0)
		return acquire_sem(mutexp->sem);
	return 0;
#endif
}
Esempio n. 5
0
TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset)
{/*{{{*/
	TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Changed sigmask in thread: %ld", tsrm_thread_id()));
	/* TODO: add support for other APIs */
#ifdef PTHREADS
	return pthread_sigmask(how, set, oldset);
#else
	return sigprocmask(how, set, oldset);
#endif
}/*}}}*/
Esempio n. 6
0
/* allocates a new interpreter context */
void *tsrm_new_interpreter_context(void)
{/*{{{*/
	tsrm_tls_entry *new_ctx, *current;
	THREAD_T thread_id;

	thread_id = tsrm_thread_id();
	tsrm_mutex_lock(tsmm_mutex);

	current = tsrm_tls_get();

	allocate_new_resource(&new_ctx, thread_id);

	/* switch back to the context that was in use prior to our creation
	 * of the new one */
	return tsrm_set_interpreter_context(current);
}/*}}}*/
Esempio n. 7
0
static void lcg_seed(TSRMLS_D) /* {{{ */
{
	struct timeval tv;

	if (gettimeofday(&tv, NULL) == 0) {
		LCG(s1) = tv.tv_sec ^ (~tv.tv_usec);
	} else {
		LCG(s1) = 1;
	}
#ifdef ZTS
	LCG(s2) = (long) tsrm_thread_id();
#else
	LCG(s2) = (long) getpid();
#endif

	LCG(seeded) = 1;
}
Esempio n. 8
0
/*
  Unlock a mutex.
  A return value of 0 indicates success
*/
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
{/*{{{*/
	TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex unlocked thread: %ld", tsrm_thread_id()));
#ifdef TSRM_WIN32
	LeaveCriticalSection(mutexp);
	return 0;
#elif defined(GNUPTH)
	if (pth_mutex_release(mutexp)) {
		return 0;
	}
	return -1;
#elif defined(PTHREADS)
	return pthread_mutex_unlock(mutexp);
#elif defined(TSRM_ST)
	return st_mutex_unlock(mutexp);
#endif
}/*}}}*/
Esempio n. 9
0
/* {{{ mysqlnd_res_meta::func_enter */
static zend_bool
MYSQLND_METHOD(mysqlnd_debug, func_enter)(MYSQLND_DEBUG * self,
										  unsigned int line, const char * const file,
										  char * func_name, unsigned int func_name_len)
{
#ifdef MYSQLND_THREADED
	MYSQLND_ZTS(self);
#endif
	if ((self->flags & MYSQLND_DEBUG_DUMP_TRACE) == 0 || self->file_name == NULL) {
		return FALSE;
	}
#ifdef MYSQLND_THREADED
	if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
		return FALSE; /* don't trace background threads */
	}
#endif
	if (zend_stack_count(&self->call_stack) >= self->nest_level_limit) {
		return FALSE;
	}

	if ((self->flags & MYSQLND_DEBUG_TRACE_MEMORY_CALLS) == 0 && 
		(func_name == mysqlnd_emalloc_name	|| func_name == mysqlnd_pemalloc_name	||
		 func_name == mysqlnd_ecalloc_name	|| func_name == mysqlnd_pecalloc_name	||
		 func_name == mysqlnd_erealloc_name || func_name == mysqlnd_perealloc_name	||
		 func_name == mysqlnd_efree_name	|| func_name == mysqlnd_pefree_name		|| 
		 func_name == mysqlnd_malloc_name	|| func_name == mysqlnd_calloc_name		|| 
		 func_name == mysqlnd_realloc_name	|| func_name == mysqlnd_free_name		||
		 func_name == mysqlnd_palloc_zval_ptr_dtor_name	|| func_name == mysqlnd_palloc_get_zval_name ||
		 func_name == mysqlnd_read_header_name || func_name == mysqlnd_read_body_name)) {
		zend_stack_push(&self->call_stack, "", sizeof(""));
	   	return FALSE;
	}

	zend_stack_push(&self->call_stack, func_name, func_name_len + 1);

	if (zend_hash_num_elements(&self->not_filtered_functions) &&
		0 == zend_hash_exists(&self->not_filtered_functions, func_name, strlen(func_name) + 1))
	{
		return FALSE;
	}

	self->m->log_va(self, line, file, zend_stack_count(&self->call_stack) - 1, NULL, ">%s", func_name);
	return TRUE;
}
Esempio n. 10
0
/* frees all resources allocated for all threads except current */
void ts_free_worker_threads(void)
{/*{{{*/
	tsrm_tls_entry *thread_resources;
	int i;
	THREAD_T thread_id = tsrm_thread_id();
	int hash_value;
	tsrm_tls_entry *last=NULL;

	tsrm_mutex_lock(tsmm_mutex);
	hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
	thread_resources = tsrm_tls_table[hash_value];

	while (thread_resources) {
		if (thread_resources->thread_id != thread_id) {
			for (i=0; i<thread_resources->count; i++) {
				if (resource_types_table[i].dtor) {
					resource_types_table[i].dtor(thread_resources->storage[i]);
				}
			}
			for (i=0; i<thread_resources->count; i++) {
				free(thread_resources->storage[i]);
			}
			free(thread_resources->storage);
			if (last) {
				last->next = thread_resources->next;
			} else {
				tsrm_tls_table[hash_value] = thread_resources->next;
			}
			free(thread_resources);
			if (last) {
				thread_resources = last->next;
			} else {
				thread_resources = tsrm_tls_table[hash_value];
			}
		} else {
			if (thread_resources->next) {
				last = thread_resources;
			}
			thread_resources = thread_resources->next;
		}
	}
	tsrm_mutex_unlock(tsmm_mutex);
}/*}}}*/
Esempio n. 11
0
static void lcg_seed(void) /* {{{ */
{
	struct timeval tv;

	if (gettimeofday(&tv, NULL) == 0) {
		LCG(s1) = tv.tv_sec ^ (tv.tv_usec<<11);
	} else {
		LCG(s1) = 1;
	}
#ifdef ZTS
	LCG(s2) = (zend_long) tsrm_thread_id();
#else
	LCG(s2) = (zend_long) getpid();
#endif

	/* Add entropy to s2 by calling gettimeofday() again */
	if (gettimeofday(&tv, NULL) == 0) {
		LCG(s2) ^= (tv.tv_usec<<11);
	}

	LCG(seeded) = 1;
}
Esempio n. 12
0
/* fetches the requested resource for the current thread */
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id)
{
	THREAD_T thread_id;
	int hash_value;
	tsrm_tls_entry *thread_resources;

#ifdef NETWARE
	/* The below if loop is added for NetWare to fix an abend while unloading PHP
	 * when an Apache unload command is issued on the system console.
	 * While exiting from PHP, at the end for some reason, this function is called
	 * with tsrm_tls_table = NULL. When this happened, the server abends when
	 * tsrm_tls_table is accessed since it is NULL.
	 */
	if(tsrm_tls_table) {
#endif
	if (!th_id) {
		/* Fast path for looking up the resources for the current
		 * thread. Its used by just about every call to
		 * ts_resource_ex(). This avoids the need for a mutex lock
		 * and our hashtable lookup.
		 */
		thread_resources = tsrm_tls_get();

		if (thread_resources) {
			TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for current thread %d", id, (long) thread_resources->thread_id));
			/* Read a specific resource from the thread's resources.
			 * This is called outside of a mutex, so have to be aware about external
			 * changes to the structure as we read it.
			 */
			TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
		}
		thread_id = tsrm_thread_id();
	} else {
		thread_id = *th_id;
	}

	TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for thread %ld", id, (long) thread_id));
	tsrm_mutex_lock(tsmm_mutex);

	hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
	thread_resources = tsrm_tls_table[hash_value];

	if (!thread_resources) {
		allocate_new_resource(&tsrm_tls_table[hash_value], thread_id);
		return ts_resource_ex(id, &thread_id);
	} else {
		 do {
			if (thread_resources->thread_id == thread_id) {
				break;
			}
			if (thread_resources->next) {
				thread_resources = thread_resources->next;
			} else {
				allocate_new_resource(&thread_resources->next, thread_id);
				return ts_resource_ex(id, &thread_id);
				/*
				 * thread_resources = thread_resources->next;
				 * break;
				 */
			}
		 } while (thread_resources);
	}
	tsrm_mutex_unlock(tsmm_mutex);
	/* Read a specific resource from the thread's resources.
	 * This is called outside of a mutex, so have to be aware about external
	 * changes to the structure as we read it.
	 */
	TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
#ifdef NETWARE
	}	/* if(tsrm_tls_table) */
#endif
}
Esempio n. 13
0
void zend_accel_error(int type, const char *format, ...)
{
    va_list args;
	time_t timestamp;
	char *time_string;
	FILE * fLog = NULL;

	if (type > ZCG(accel_directives).log_verbosity_level) {
		return;
	}

	timestamp = time(NULL);
	time_string = asctime(localtime(&timestamp));
	time_string[24] = 0;

	if (!ZCG(accel_directives).error_log ||
	    !*ZCG(accel_directives).error_log ||
	    strcmp(ZCG(accel_directives).error_log, "stderr") == 0) {

		fLog = stderr;
	} else {
		fLog = fopen(ZCG(accel_directives).error_log, "a+");
		if (!fLog) {
			fLog = stderr;
		}
	}

#ifdef ZTS
    fprintf(fLog, "%s (" ZEND_ULONG_FMT "): ", time_string, (zend_ulong)tsrm_thread_id());
#else
    fprintf(fLog, "%s (%d): ", time_string, getpid());
#endif

	switch (type) {
		case ACCEL_LOG_FATAL:
			fprintf(fLog, "Fatal Error ");
			break;
		case ACCEL_LOG_ERROR:
			fprintf(fLog, "Error ");
			break;
		case ACCEL_LOG_WARNING:
			fprintf(fLog, "Warning ");
			break;
		case ACCEL_LOG_INFO:
			fprintf(fLog, "Message ");
			break;
		case ACCEL_LOG_DEBUG:
			fprintf(fLog, "Debug ");
			break;
	}

    va_start(args, format);
    vfprintf(fLog, format, args);
    va_end(args);
	fprintf(fLog, "\n");
	switch (type) {
		case ACCEL_LOG_ERROR:
			zend_bailout();
			break;
		case ACCEL_LOG_FATAL:
			exit(-2);
			break;
	}
	fflush(fLog);
	if (fLog != stderr) {
		fclose(fLog);
	}
}
Esempio n. 14
0
void call_backtrace(int fd, zend_backtrace_globals* g, backtrace_callback_t callback)
{
#ifdef DEBUG
	fprintf(stderr, "[%d]: call_backtrace()\n", getpid());
	fflush(stderr);
#endif

	if (!callback) {
		return;
	}

	HashPosition pos;
	void** current;
	THREAD_T self = tsrm_thread_id();
	int processed_self = 0;

	tsrm_mutex_lock(mutex);

	for (
			zend_hash_internal_pointer_reset_ex(&thread_ids, &pos);
			SUCCESS == zend_hash_get_current_data_ex(&thread_ids, (void**)&current, &pos);
			zend_hash_move_forward_ex(&thread_ids, &pos)
	)
	{
		char* key;
		uint key_len;
		ulong idx;
		int type;

		type = zend_hash_get_current_key_ex(&thread_ids, &key, &key_len, &idx, 0, &pos);
		if (HASH_KEY_IS_STRING == type) {
			idx = atol(key);
		}

#ifdef DEBUG
		fprintf(stderr, "[%d]: Trying thread %lu\n", getpid(), idx);
		fflush(stderr);
#endif

		if (idx) {
#if defined(PTHREADS)
			int res = pthread_kill((pthread_t)idx, 0);
			if (res) {
				continue;
			}
#elif defined(GNUPTH)
			int res = pth_raise((pth_t)idx, 0);
			if (!res) {
				continue;
			}
#endif

#ifdef DEBUG
			fprintf(stderr, "[%d]: Processing thread %lu\n", getpid(), idx);
			fflush(stderr);
#endif

			THREAD_T thread_id = idx;

#if defined(PTHREADS)
			if (!processed_self && pthread_equal(thread_id, self)) {
				processed_self = 1;
			}
#else
			if (thread_id == self) {
				processed_self = 1;
			}
#endif

			void*** tsrm_ls = (void***)ts_resource_ex(0, &thread_id);
			callback(fd, g, tsrm_ls);
#ifdef DEBUG
			fprintf(stderr, "[%d]: Processed thread %lu\n", getpid(), idx);
			fflush(stderr);
#endif
		}
	}

	if (!processed_self) {
#ifdef DEBUG
		fprintf(stderr, "[%d]: Processing self\n", getpid());
		fflush(stderr);
#endif
		void*** tsrm_ls = (void***)ts_resource_ex(0, (THREAD_T*)0);
		callback(fd, g, tsrm_ls);
#ifdef DEBUG
		fprintf(stderr, "[%d]: Processed self\n", getpid());
		fflush(stderr);
#endif
	}

	tsrm_mutex_unlock(mutex);
}
Esempio n. 15
0
static ulong php_http_openssl_thread_id(void)
{
	return (ulong) tsrm_thread_id();
}
Esempio n. 16
0
/* {{{ mysqlnd_debug::log */
static enum_func_status
MYSQLND_METHOD(mysqlnd_debug, log)(MYSQLND_DEBUG * self,
								   unsigned int line, const char * const file,
								   unsigned int level, const char * type, const char * message)
{
	char pipe_buffer[512];
	enum_func_status ret;
	int i;
	char * message_line;
	unsigned int message_line_len;
	unsigned int flags = self->flags;
	char pid_buffer[10], time_buffer[30], file_buffer[200],
		 line_buffer[6], level_buffer[7];
	MYSQLND_ZTS(self);

#ifdef MYSQLND_THREADED
	if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
		return PASS; /* don't trace background threads */
	}
#endif

	if (!self->stream) {
		if (FAIL == self->m->open(self, FALSE)) {
			return FAIL;
		}
	}

	if (level == -1) {
		level = zend_stack_count(&self->call_stack);
	}
	i = MIN(level, sizeof(pipe_buffer) / 2  - 1);
	pipe_buffer[i*2] = '\0';
	for (;i > 0;i--) {
		pipe_buffer[i*2 - 1] = ' ';
		pipe_buffer[i*2 - 2] = '|';
	}


	if (flags & MYSQLND_DEBUG_DUMP_PID) {
		snprintf(pid_buffer, sizeof(pid_buffer) - 1, "%5u: ", self->pid);
		pid_buffer[sizeof(pid_buffer) - 1 ] = '\0';
	}
	if (flags & MYSQLND_DEBUG_DUMP_TIME) {
		/* The following from FF's DBUG library, which is in the public domain */
#if defined(PHP_WIN32)
		/* FIXME This doesn't give microseconds as in Unix case, and the resolution is
		in system ticks, 10 ms intervals. See my_getsystime.c for high res */
		SYSTEMTIME loc_t;
		GetLocalTime(&loc_t);
		snprintf(time_buffer, sizeof(time_buffer) - 1,
				 /* "%04d-%02d-%02d " */
				 "%02d:%02d:%02d.%06d ",
				 /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/
				 loc_t.wHour, loc_t.wMinute, loc_t.wSecond, loc_t.wMilliseconds);
		time_buffer[sizeof(time_buffer) - 1 ] = '\0';
#else
		struct timeval tv;
		struct tm *tm_p;
		if (gettimeofday(&tv, NULL) != -1) {
			if ((tm_p= localtime((const time_t *)&tv.tv_sec))) {
				snprintf(time_buffer, sizeof(time_buffer) - 1,
						 /* "%04d-%02d-%02d " */
						 "%02d:%02d:%02d.%06d ",
						 /*tm_p->tm_year + 1900, tm_p->tm_mon + 1, tm_p->tm_mday,*/
						 tm_p->tm_hour, tm_p->tm_min, tm_p->tm_sec,
						 (int) (tv.tv_usec));
				time_buffer[sizeof(time_buffer) - 1 ] = '\0';
			}
		}
#endif
	}
	if (flags & MYSQLND_DEBUG_DUMP_FILE) {
		snprintf(file_buffer, sizeof(file_buffer) - 1, "%14s: ", file);
		file_buffer[sizeof(file_buffer) - 1 ] = '\0';
	}
	if (flags & MYSQLND_DEBUG_DUMP_LINE) {
		snprintf(line_buffer, sizeof(line_buffer) - 1, "%5u: ", line);
		line_buffer[sizeof(line_buffer) - 1 ] = '\0';
	}
	if (flags & MYSQLND_DEBUG_DUMP_LEVEL) {
		snprintf(level_buffer, sizeof(level_buffer) - 1, "%4u: ", level);
		level_buffer[sizeof(level_buffer) - 1 ] = '\0';
	}

	message_line_len = spprintf(&message_line, 0, "%s%s%s%s%s%s%s%s\n",
								flags & MYSQLND_DEBUG_DUMP_PID? pid_buffer:"",
								flags & MYSQLND_DEBUG_DUMP_TIME? time_buffer:"",
								flags & MYSQLND_DEBUG_DUMP_FILE? file_buffer:"",
								flags & MYSQLND_DEBUG_DUMP_LINE? line_buffer:"",
								flags & MYSQLND_DEBUG_DUMP_LEVEL? level_buffer:"",
								pipe_buffer, type? type:"", message);

	ret = php_stream_write(self->stream, message_line, message_line_len)? PASS:FAIL;
	efree(message_line);
	if (flags & MYSQLND_DEBUG_FLUSH) {
		self->m->close(self);
		self->m->open(self, TRUE);	
	}
	return ret;
}