diff --git a/UPGRADING b/UPGRADING index fc832ba2e37b2..ed75b814e8619 100644 --- a/UPGRADING +++ b/UPGRADING @@ -404,6 +404,11 @@ PHP 8.0 UPGRADE NOTES explicit setlocale() call is now always required if you wish to change any locale component from the default. +- Sysvsem: + . sem_get() will now return an Sysvsem object rather than a resource. + Return value checks using is_resource() should be replaced with checks + for `false`. + - tidy: . The $use_include_path parameter, which was not used internally, has been removed from tidy_repair_string(). diff --git a/ext/sysvsem/php_sysvsem.h b/ext/sysvsem/php_sysvsem.h index 980ddbe021316..f4708942f787b 100644 --- a/ext/sysvsem/php_sysvsem.h +++ b/ext/sysvsem/php_sysvsem.h @@ -27,25 +27,15 @@ extern zend_module_entry sysvsem_module_entry; PHP_MINIT_FUNCTION(sysvsem); PHP_MINFO_FUNCTION(sysvsem); -PHP_FUNCTION(sem_get); -PHP_FUNCTION(sem_acquire); -PHP_FUNCTION(sem_release); -PHP_FUNCTION(sem_remove); typedef struct { - int le_sem; -} sysvsem_module; - -typedef struct { - int id; /* For error reporting. */ int key; /* For error reporting. */ int semid; /* Returned by semget(). */ int count; /* Acquire count for auto-release. */ int auto_release; /* flag that says to auto-release. */ + zend_object std; } sysvsem_sem; -extern sysvsem_module php_sysvsem_module; - #else #define sysvsem_module_ptr NULL diff --git a/ext/sysvsem/sysvsem.c b/ext/sysvsem/sysvsem.c index b5e8adb91fe6b..b9f1e626a7b9f 100644 --- a/ext/sysvsem/sysvsem.c +++ b/ext/sysvsem/sysvsem.c @@ -39,6 +39,7 @@ #include "sysvsem_arginfo.h" #include "php_sysvsem.h" #include "ext/standard/info.h" +#include "Zend/zend_interfaces.h" #if !HAVE_SEMUN @@ -74,9 +75,6 @@ zend_module_entry sysvsem_module_entry = { ZEND_GET_MODULE(sysvsem) #endif - -THREAD_LS sysvsem_module php_sysvsem_module; - /* Semaphore functions using System V semaphores. Each semaphore * actually consists of three semaphores allocated as a unit under the * same key. Semaphore 0 (SYSVSEM_SEM) is the actual semaphore, it is @@ -96,11 +94,35 @@ THREAD_LS sysvsem_module php_sysvsem_module; #define SYSVSEM_USAGE 1 #define SYSVSEM_SETVAL 2 -/* {{{ release_sysvsem_sem - */ -static void release_sysvsem_sem(zend_resource *rsrc) +/* Sysvsem class */ + +zend_class_entry *sysvsem_ce; +static zend_object_handlers sysvsem_object_handlers; + +static inline sysvsem_sem *sysvsem_from_obj(zend_object *obj) { + return (sysvsem_sem *)((char *)(obj) - XtOffsetOf(sysvsem_sem, std)); +} + +#define Z_SYSVSEM_P(zv) sysvsem_from_obj(Z_OBJ_P(zv)) + +static zend_object *sysvsem_create_object(zend_class_entry *class_type) { + sysvsem_sem *intern = zend_object_alloc(sizeof(sysvsem_sem), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &sysvsem_object_handlers; + + return &intern->std; +} + +static zend_function *sysvsem_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct Sysvsem, use sem_get() instead"); + return NULL; +} + +static void sysvsem_free_obj(zend_object *object) { - sysvsem_sem *sem_ptr = (sysvsem_sem *)rsrc->ptr; + sysvsem_sem *sem_ptr = sysvsem_from_obj(object); struct sembuf sop[2]; int opcount = 1; /* @@ -130,7 +152,8 @@ static void release_sysvsem_sem(zend_resource *rsrc) } semop(sem_ptr->semid, sop, opcount); - efree(sem_ptr); + + zend_object_std_dtor(&sem_ptr->std); } /* }}} */ @@ -138,7 +161,20 @@ static void release_sysvsem_sem(zend_resource *rsrc) */ PHP_MINIT_FUNCTION(sysvsem) { - php_sysvsem_module.le_sem = zend_register_list_destructors_ex(release_sysvsem_sem, NULL, "sysvsem", module_number); + zend_class_entry ce; + INIT_CLASS_ENTRY(ce, "Sysvsem", class_Sysvsem_methods); + sysvsem_ce = zend_register_internal_class(&ce); + sysvsem_ce->ce_flags |= ZEND_ACC_FINAL; + sysvsem_ce->create_object = sysvsem_create_object; + sysvsem_ce->serialize = zend_class_serialize_deny; + sysvsem_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&sysvsem_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + sysvsem_object_handlers.offset = XtOffsetOf(sysvsem_sem, std); + sysvsem_object_handlers.free_obj = sysvsem_free_obj; + sysvsem_object_handlers.get_constructor = sysvsem_get_constructor; + sysvsem_object_handlers.clone_obj = NULL; + return SUCCESS; } /* }}} */ @@ -159,7 +195,7 @@ PHP_MINFO_FUNCTION(sysvsem) #undef SETVAL_WANTS_PTR #endif -/* {{{ proto resource sem_get(int key [, int max_acquire [, int perm [, int auto_release]]) +/* {{{ proto Sysvsem sem_get(int key [, int max_acquire [, int perm [, int auto_release]]) Return an id for the semaphore with the given key, and allow max_acquire (default 1) processes to acquire it simultaneously */ PHP_FUNCTION(sem_get) { @@ -259,14 +295,13 @@ PHP_FUNCTION(sem_get) } } - sem_ptr = (sysvsem_sem *) emalloc(sizeof(sysvsem_sem)); + object_init_ex(return_value, sysvsem_ce); + + sem_ptr = Z_SYSVSEM_P(return_value); sem_ptr->key = key; sem_ptr->semid = semid; sem_ptr->count = 0; sem_ptr->auto_release = auto_release; - - RETVAL_RES(zend_register_resource(sem_ptr, php_sysvsem_module.le_sem)); - sem_ptr->id = Z_RES_HANDLE_P(return_value); } /* }}} */ @@ -280,21 +315,19 @@ static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire) struct sembuf sop; if (acquire) { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|b", &arg_id, &nowait) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &arg_id, sysvsem_ce, &nowait) == FAILURE) { RETURN_THROWS(); } } else { - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg_id) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg_id, sysvsem_ce) == FAILURE) { RETURN_THROWS(); } } - if ((sem_ptr = (sysvsem_sem *)zend_fetch_resource(Z_RES_P(arg_id), "SysV semaphore", php_sysvsem_module.le_sem)) == NULL) { - RETURN_THROWS(); - } + sem_ptr = Z_SYSVSEM_P(arg_id); if (!acquire && sem_ptr->count == 0) { - php_error_docref(NULL, E_WARNING, "SysV semaphore " ZEND_LONG_FMT " (key 0x%x) is not currently acquired", Z_LVAL_P(arg_id), sem_ptr->key); + php_error_docref(NULL, E_WARNING, "SysV semaphore for key 0x%x is not currently acquired", sem_ptr->key); RETURN_FALSE; } @@ -316,7 +349,7 @@ static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire) } /* }}} */ -/* {{{ proto bool sem_acquire(resource id) +/* {{{ proto bool sem_acquire(Sysvsem id) Acquires the semaphore with the given id, blocking if necessary */ PHP_FUNCTION(sem_acquire) { @@ -324,7 +357,7 @@ PHP_FUNCTION(sem_acquire) } /* }}} */ -/* {{{ proto bool sem_release(resource id) +/* {{{ proto bool sem_release(Sysvsem id) Releases the semaphore with the given id */ PHP_FUNCTION(sem_release) { @@ -332,7 +365,7 @@ PHP_FUNCTION(sem_release) } /* }}} */ -/* {{{ proto bool sem_remove(resource id) +/* {{{ proto bool sem_remove(Sysvsem id) Removes semaphore from Unix systems */ /* @@ -349,13 +382,11 @@ PHP_FUNCTION(sem_remove) struct semid_ds buf; #endif - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg_id) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg_id, sysvsem_ce) == FAILURE) { RETURN_THROWS(); } - if ((sem_ptr = (sysvsem_sem *)zend_fetch_resource(Z_RES_P(arg_id), "SysV semaphore", php_sysvsem_module.le_sem)) == NULL) { - RETURN_THROWS(); - } + sem_ptr = Z_SYSVSEM_P(arg_id); #if HAVE_SEMUN un.buf = &buf; @@ -363,7 +394,7 @@ PHP_FUNCTION(sem_remove) #else if (semctl(sem_ptr->semid, 0, IPC_STAT, NULL) < 0) { #endif - php_error_docref(NULL, E_WARNING, "SysV semaphore " ZEND_LONG_FMT " does not (any longer) exist", Z_LVAL_P(arg_id)); + php_error_docref(NULL, E_WARNING, "SysV semaphore for key 0x%x does not (any longer) exist", sem_ptr->key); RETURN_FALSE; } @@ -372,7 +403,7 @@ PHP_FUNCTION(sem_remove) #else if (semctl(sem_ptr->semid, 0, IPC_RMID, NULL) < 0) { #endif - php_error_docref(NULL, E_WARNING, "Failed for SysV semaphore " ZEND_LONG_FMT ": %s", Z_LVAL_P(arg_id), strerror(errno)); + php_error_docref(NULL, E_WARNING, "Failed for SysV semaphore for key 0x%x: %s", sem_ptr->key, strerror(errno)); RETURN_FALSE; } diff --git a/ext/sysvsem/sysvsem.stub.php b/ext/sysvsem/sysvsem.stub.php index 152689a795145..e6fe1b4b7d8cf 100644 --- a/ext/sysvsem/sysvsem.stub.php +++ b/ext/sysvsem/sysvsem.stub.php @@ -2,23 +2,17 @@ /** @generate-function-entries */ +final class Sysvsem +{ +} + /** * @todo use bool for $auto_release - * @return resource|false */ -function sem_get(int $key, int $max_acquire = 1, int $perm = 0666, int $auto_release = 1) {} +function sem_get(int $key, int $max_acquire = 1, int $perm = 0666, int $auto_release = 1): Sysvsem|false {} -/** - * @param resource $sem_identifier - */ -function sem_acquire($sem_identifier, bool $nowait = false): bool {} +function sem_acquire(Sysvsem $sem_identifier, bool $nowait = false): bool {} -/** - * @param resource $sem_identifier - */ -function sem_release($sem_identifier): bool {} +function sem_release(Sysvsem $sem_identifier): bool {} -/** - * @param resource $sem_identifier - */ -function sem_remove($sem_identifier): bool {} +function sem_remove(Sysvsem $sem_identifier): bool {} diff --git a/ext/sysvsem/sysvsem_arginfo.h b/ext/sysvsem/sysvsem_arginfo.h index 2edb26534fc68..83948fed3f789 100644 --- a/ext/sysvsem/sysvsem_arginfo.h +++ b/ext/sysvsem/sysvsem_arginfo.h @@ -1,6 +1,6 @@ /* This is a generated file, edit the .stub.php file instead. */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_sem_get, 0, 0, 1) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_sem_get, 0, 1, Sysvsem, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, key, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, max_acquire, IS_LONG, 0, "1") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, perm, IS_LONG, 0, "0666") @@ -8,12 +8,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_sem_get, 0, 0, 1) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sem_acquire, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, sem_identifier) + ZEND_ARG_OBJ_INFO(0, sem_identifier, Sysvsem, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, nowait, _IS_BOOL, 0, "false") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_sem_release, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, sem_identifier) + ZEND_ARG_OBJ_INFO(0, sem_identifier, Sysvsem, 0) ZEND_END_ARG_INFO() #define arginfo_sem_remove arginfo_sem_release @@ -32,3 +32,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(sem_remove, arginfo_sem_remove) ZEND_FE_END }; + + +static const zend_function_entry class_Sysvsem_methods[] = { + ZEND_FE_END +}; diff --git a/ext/sysvsem/tests/nowait.phpt b/ext/sysvsem/tests/nowait.phpt index 147b8da335f56..892a3757b5dad 100644 --- a/ext/sysvsem/tests/nowait.phpt +++ b/ext/sysvsem/tests/nowait.phpt @@ -18,42 +18,42 @@ pcntl_signal(SIGCHLD, SIG_IGN); // Get semaphore for parent $p_sem_id = sem_get($P_SEMKEY, 1); if ($p_sem_id === FALSE) { - echo "P: failed to parent get semaphore\n"; + echo "P: failed to parent get semaphore.\n"; exit; } -echo "P: got semaphore $p_sem_id.\n"; +echo "P: got semaphore.\n"; // Get semaphore for child $c_sem_id = sem_get($C_SEMKEY, 1); if ($c_sem_id === FALSE) { - echo "P: failed to child get semaphore\n"; + echo "P: failed to child get semaphore.\n"; exit; } // Acquire semaphore for parent if (!sem_acquire($p_sem_id)) { - echo "P: fail to acquire semaphore $p_sem_id.\n"; + echo "P: fail to acquire semaphore.\n"; sem_remove($p_sem_id); exit; } -echo "P: acquired semaphore $p_sem_id.\n"; +echo "P: acquired semaphore.\n"; // Acquire semaphore for child if (!sem_acquire($c_sem_id)) { - echo "P: fail to acquire semaphore $c_sem_id.\n"; + echo "P: failed to acquire semaphore.\n"; sem_remove($c_sem_id); exit; } -echo "P: acquired semaphore $c_sem_id\n"; +echo "P: acquired semaphore.\n"; // Fork process $pid = pcntl_fork(); if ($pid) { register_shutdown_function(function () use ($p_sem_id) { - echo "P: removing semaphore $p_sem_id.\n"; + echo "P: removing semaphore.\n"; sem_remove($p_sem_id); }); @@ -63,7 +63,7 @@ if ($pid) { /* Wait for the child semaphore to be released to to release the parent semaphore */ if (!sem_acquire($c_sem_id)) { - echo "P: failed to acquire semaphore $c_sem_id.\n"; + echo "P: failed to acquire semaphore.\n"; exit; } @@ -72,9 +72,9 @@ if ($pid) { the child continue execution */ sem_release($c_sem_id); - echo "P: releasing semaphore $p_sem_id.\n"; + echo "P: releasing semaphore.\n"; if (!sem_release($p_sem_id)) { - echo "P: failed to release semaphore\n"; + echo "P: failed to release semaphore.\n"; } $status = null; @@ -83,52 +83,52 @@ if ($pid) { } else { register_shutdown_function(function () use ($c_sem_id) { - echo "C: removing semaphore $c_sem_id.\n"; + echo "C: removing semaphore.\n"; sem_remove($c_sem_id); }); echo "C: child process running.\n"; // Have the semaphore after process forked - echo "C: got semaphore $p_sem_id and $c_sem_id.\n"; + echo "C: got semaphores.\n"; // This should fail to get to the semaphore and not wait if (sem_acquire($p_sem_id, true)) { - echo "C: test failed, Child was able to acquire semaphore $p_sem_id.\n"; + echo "C: test failed, Child was able to acquire semaphore.\n"; exit; } // The child process did not wait to acquire the semaphore - echo "C: failed to acquire semaphore $p_sem_id.\n"; + echo "C: failed to acquire semaphore.\n"; - echo "C: releasing semaphore $c_sem_id\n"; + echo "C: releasing semaphore.\n"; if (!sem_release($c_sem_id)) { - echo "C: Failed to release semaphore\n"; + echo "C: failed to release semaphore.\n"; } // Acquire semaphore with waiting if (!sem_acquire($p_sem_id)) { - echo "C: fail to acquire semaphore $p_sem_id.\n"; + echo "C: fail to acquire semaphore.\n"; exit; } - echo "C: success acquired semaphore $p_sem_id.\n"; + echo "C: success acquired semaphore.\n"; - echo "C: releasing semaphore $p_sem_id.\n"; + echo "C: releasing semaphore.\n"; sem_release($p_sem_id); } ?> --EXPECTF-- P: parent process running. -P: got semaphore Resource id #%i. -P: acquired semaphore Resource id #%i. -P: acquired semaphore Resource id #%i +P: got semaphore. +P: acquired semaphore. +P: acquired semaphore. C: child process running. -C: got semaphore Resource id #%i and Resource id #%i. -C: failed to acquire semaphore Resource id #%i. -C: releasing semaphore Resource id #%i -P: releasing semaphore Resource id #%i. -C: success acquired semaphore Resource id #%i. -C: releasing semaphore Resource id #%i. -C: removing semaphore Resource id #%i. -P: removing semaphore Resource id #%i. +C: got semaphores. +C: failed to acquire semaphore. +C: releasing semaphore. +P: releasing semaphore. +C: success acquired semaphore. +C: releasing semaphore. +C: removing semaphore. +P: removing semaphore. diff --git a/ext/sysvsem/tests/sysv.phpt b/ext/sysvsem/tests/sysv.phpt index 08cb63f839098..aa2e7d10411c7 100644 --- a/ext/sysvsem/tests/sysv.phpt +++ b/ext/sysvsem/tests/sysv.phpt @@ -19,15 +19,15 @@ if ($sem_id === FALSE) { echo "Fail to get semaphore"; exit; } -echo "Got semaphore $sem_id.\n"; +echo "Got semaphore.\n"; // Accuire semaphore if (! sem_acquire($sem_id)) { - echo "Fail to acquire semaphore $sem_id.\n"; + echo "Fail to acquire semaphore.\n"; sem_remove($sem_id); exit; } -echo "Success acquire semaphore $sem_id.\n"; +echo "Success acquire semaphore.\n"; $shm_id = shm_attach($SHMKEY, $MEMSIZE); if ($shm_id === FALSE) { @@ -72,9 +72,9 @@ if ($var1 === FALSE) { } // Release semaphore if (!sem_release($sem_id)) { - echo "Fail to release $sem_id semaphore.\n"; + echo "Fail to release semaphore.\n"; } else { - echo "Semaphore $sem_id released.\n"; + echo "Semaphore released.\n"; } // remove shared memory segmant from SysV @@ -88,7 +88,7 @@ if (shm_remove ($shm_id)) { if (sem_remove($sem_id)) { echo "semaphore removed successfully from SysV.\n"; } else { - echo "Fail to remove $sem_id semaphore from SysV.\n"; + echo "Fail to remove semaphore from SysV.\n"; } echo "End.\n"; /* NOTE: assigned semids differ depending on the kernel, since @@ -99,14 +99,14 @@ echo "End.\n"; ?> --EXPECTF-- Start. -Got semaphore Resource id #%i. -Success acquire semaphore Resource id #%i. +Got semaphore. +Success acquire semaphore. Success to attach shared memory : %s. Write var1 to shared memory. Write var2 to shared memory. Read var1=Variable 1. Read var2=Variable 2. -Semaphore Resource id #%s released. +Semaphore released. Shared memory successfully removed from SysV. semaphore removed successfully from SysV. End.