Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two methods added to AMQPConnection: #89

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 53 additions & 8 deletions amqp.c
Expand Up @@ -56,6 +56,10 @@
# include <unistd.h>
#endif

/* AMQP module global structure declaration */
ZEND_DECLARE_MODULE_GLOBALS(amqp);
static PHP_GINIT_FUNCTION(amqp);

/* True global resources - no need for thread safety here */
zend_class_entry *amqp_connection_class_entry;
zend_class_entry *amqp_channel_class_entry;
Expand Down Expand Up @@ -153,6 +157,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_amqp_connection_class_setWriteTimeout, ZEND_SEND_
ZEND_ARG_INFO(0, timeout)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_amqp_connection_class_attachSignal, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
ZEND_ARG_INFO(0, signo)
ZEND_ARG_INFO(0, callback)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_amqp_connection_class_detachSignal, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
ZEND_ARG_INFO(0, signo)
ZEND_END_ARG_INFO()

/* amqp_channel_class ARG_INFO definition */
ZEND_BEGIN_ARG_INFO_EX(arginfo_amqp_channel_class__construct, ZEND_SEND_BY_VAL, ZEND_RETURN_VALUE, 1)
Expand Down Expand Up @@ -456,6 +468,9 @@ zend_function_entry amqp_connection_class_functions[] = {
PHP_ME(amqp_connection_class, getWriteTimeout, arginfo_amqp_connection_class_getWriteTimeout, ZEND_ACC_PUBLIC)
PHP_ME(amqp_connection_class, setWriteTimeout, arginfo_amqp_connection_class_setWriteTimeout, ZEND_ACC_PUBLIC)

PHP_ME(amqp_connection_class, attachSignal, arginfo_amqp_connection_class_attachSignal, ZEND_ACC_PUBLIC)
PHP_ME(amqp_connection_class, detachSignal, arginfo_amqp_connection_class_detachSignal, ZEND_ACC_PUBLIC)

{NULL, NULL, NULL} /* Must be the last line in amqp_functions[] */
};

Expand Down Expand Up @@ -579,20 +594,24 @@ zend_function_entry amqp_functions[] = {
/* {{{ amqp_module_entry
*/
zend_module_entry amqp_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"amqp",
amqp_functions,
PHP_MINIT(amqp),
PHP_MSHUTDOWN(amqp),
PHP_RINIT(amqp),
PHP_RSHUTDOWN(amqp),
PHP_MINFO(amqp),
#if ZEND_MODULE_API_NO >= 20010901
PHP_AMQP_VERSION,
#endif
PHP_MODULE_GLOBALS(amqp),
PHP_GINIT(amqp),
NULL,
NULL,
PHP_MINFO(amqp),
#if ZEND_MODULE_API_NO >= 20010901
PHP_AMQP_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */

Expand Down Expand Up @@ -868,6 +887,32 @@ PHP_MINFO_FUNCTION(amqp)
}
/* }}} */

/* {{{ PHP_GINIT_FUNCTION
*/
static PHP_GINIT_FUNCTION(amqp)
{
memset(amqp_globals, 0, sizeof(*amqp_globals));
}
/* }}} */

/* {{{ PHP_RINIT_FUNCTION
*/
PHP_RINIT_FUNCTION(amqp)
{
zend_hash_init(&AMQP_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
return SUCCESS;
}
/* }}} */

/* {{{ PHP_RSHUTDOWN_FUNCTION
*/
PHP_RSHUTDOWN_FUNCTION(amqp)
{
zend_hash_destroy(&AMQP_G(php_signal_table));
return SUCCESS;
}
/* }}} */

/*
*Local variables:
*tab-width: 4
Expand Down
93 changes: 93 additions & 0 deletions amqp_connection.c
Expand Up @@ -489,6 +489,28 @@ zend_object_value amqp_connection_ctor(zend_class_entry *ce TSRMLS_DC)
return new_value;
}

void php_signal_callback_handler(int signo)
{
TSRMLS_FETCH();
zval *param, **handle, *retval;

/* Get php callback function */
if(zend_hash_index_find(&AMQP_G(php_signal_table), signo, (void **) &handle) == FAILURE){
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Callback function not found for signo: %d", signo);
return;
}

MAKE_STD_ZVAL(retval);
MAKE_STD_ZVAL(param);
ZVAL_NULL(retval);
ZVAL_LONG(param, signo);

/* Call the function */
call_user_function(EG(function_table), NULL, *handle, retval, 1, &param TSRMLS_CC);

zval_ptr_dtor(&param);
zval_ptr_dtor(&retval);
}

/* {{{ proto AMQPConnection::__construct([array optional])
* The array can contain 'host', 'port', 'login', 'password', 'vhost', 'read_timeout', 'write_timeout', 'connect_timeout' and 'timeout' (deprecated) indexes
Expand Down Expand Up @@ -1293,6 +1315,77 @@ PHP_METHOD(amqp_connection_class, setWriteTimeout)
}
/* }}} */

/* {{{ proto amqp::attachSignal(int signo, callback)
attach signal handler */
PHP_METHOD(amqp_connection_class, attachSignal)
{
zval *handle, **dest_handle = NULL;
char *func_name;
long signo;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &signo, &handle) == FAILURE) {
return;
}

/* Check signal code */
if (signo < 1 || signo > 32) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid signal");
RETURN_FALSE;
}

/* Check if given parameter is callable */
#if ZEND_MODULE_API_NO <= 20060613
if (!zend_is_callable(handle, 0, &func_name)) {
#else
if (!zend_is_callable(handle, 0, &func_name TSRMLS_CC)) {
#endif
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a callable function name error", func_name);
efree(func_name);
RETURN_FALSE;
}

efree(func_name);

/* Set the handler for the signal */
if (signal(signo, php_signal_callback_handler) == SIG_ERR) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while setting a signal handler for signo: %lu", signo);
RETURN_FALSE;
}

/* Add the function name to our signal table */
zend_hash_index_update(&AMQP_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
if (dest_handle) zval_add_ref(dest_handle);

RETURN_TRUE;
}
/* }}} */

/* {{{ proto amqp::detachSignal(int signo)
detach signal handler */
PHP_METHOD(amqp_connection_class, detachSignal)
{
long signo;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &signo) == FAILURE) {
return;
}

/* Check signal code */
if (signo < 1 || signo > 32) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid signal");
RETURN_FALSE;
}

/* If signal handler is registred, set SIG_DFL */
if(zend_hash_index_exists(&AMQP_G(php_signal_table), signo) && signal(signo, SIG_DFL) != SIG_ERR){
zend_hash_index_del(&AMQP_G(php_signal_table), signo);
RETURN_TRUE;
}else{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot detach signo: %lu ", signo);
RETURN_FALSE;
}
}
/* }}} */

/*
*Local variables:
Expand Down
3 changes: 3 additions & 0 deletions amqp_connection.h
Expand Up @@ -66,6 +66,9 @@ PHP_METHOD(amqp_connection_class, setReadTimeout);
PHP_METHOD(amqp_connection_class, getWriteTimeout);
PHP_METHOD(amqp_connection_class, setWriteTimeout);

PHP_METHOD(amqp_connection_class, attachSignal);
PHP_METHOD(amqp_connection_class, detachSignal);

/*
*Local variables:
*tab-width: 4
Expand Down
7 changes: 7 additions & 0 deletions php_amqp.h
Expand Up @@ -148,6 +148,8 @@ extern zend_module_entry amqp_module_entry;
PHP_MINIT_FUNCTION(amqp);
PHP_MSHUTDOWN_FUNCTION(amqp);
PHP_MINFO_FUNCTION(amqp);
PHP_RINIT_FUNCTION(amqp);
PHP_RSHUTDOWN_FUNCTION(amqp);

amqp_table_t *convert_zval_to_arguments(zval *zvalArguments);
char *stringify_bytes(amqp_bytes_t bytes);
Expand Down Expand Up @@ -399,6 +401,11 @@ typedef struct _amqp_envelope_object {
# define AMQP_OS_SOCKET_TIMEOUT_ERRNO AMQP_ERROR_CATEGORY_MASK | EAGAIN
#endif

ZEND_BEGIN_MODULE_GLOBALS(amqp);
HashTable php_signal_table;
ZEND_END_MODULE_GLOBALS(amqp);

ZEND_EXTERN_MODULE_GLOBALS(amqp);

#ifdef ZTS
#define AMQP_G(v) TSRMG(amqp_globals_id, zend_amqp_globals *, v)
Expand Down