]> granicus.if.org Git - php/commitdiff
Add an optional flag to sem_get that specifies if the semaphore should be
authorWez Furlong <wez@php.net>
Fri, 17 May 2002 12:33:49 +0000 (12:33 +0000)
committerWez Furlong <wez@php.net>
Fri, 17 May 2002 12:33:49 +0000 (12:33 +0000)
automatically released on request shutdown. (#16986)
Fix a segfault in sem_remove (#17274)

ext/sysvsem/php_sysvsem.h
ext/sysvsem/sysvsem.c

index 7d46edeacb3a771ce56891c11b05b0647f7e88be..28533d1a38b50b457282e6abfcde822dc74004ad 100644 (file)
@@ -41,6 +41,7 @@ typedef struct {
        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. */
 } sysvsem_sem;
 
 extern sysvsem_module php_sysvsem_module;
index 28b21df72bbc894f56ea345e2245891b80f38528..edc0ac340b3a714688dd2461100944bd47423e24 100644 (file)
@@ -107,13 +107,13 @@ static void release_sysvsem_sem(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
        sysvsem_sem *sem_ptr = (sysvsem_sem *)rsrc->ptr;
        struct sembuf sop[2];
-
+       int opcount = 1;
 /*
  * if count == -1, semaphore has been removed
  * Need better way to handle this
  */
 
-       if(sem_ptr->count == -1) {
+       if(sem_ptr->count == -1 || !sem_ptr->auto_release) {
                return;
        }
        /* Decrement the usage count. */
@@ -130,8 +130,10 @@ static void release_sysvsem_sem(zend_rsrc_list_entry *rsrc TSRMLS_DC)
                sop[1].sem_num = SYSVSEM_SEM;
                sop[1].sem_op  = sem_ptr->count;
                sop[1].sem_flg = SEM_UNDO;
+
+               opcount++;
        }
-       if (semop(sem_ptr->semid, sop, sem_ptr->count ? 2 : 1) == -1) {
+       if (semop(sem_ptr->semid, sop, opcount) == -1) {
                php_error(E_WARNING, "semop() failed in release_sysvsem_sem for key 0x%x: %s", sem_ptr->key, strerror(errno));
        }
 
@@ -154,12 +156,11 @@ PHP_MINIT_FUNCTION(sysvsem)
 #undef SETVAL_WANTS_PTR
 #endif
 
-/* {{{ proto int sem_get(int key [, int max_acquire [, int perm]])
+/* {{{ proto int 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)
 {
-       pval **arg_key, **arg_max_acquire, **arg_perm;
-       int key, max_acquire, perm;
+       int key, max_acquire, perm, auto_release = 1;
     int semid;
        struct sembuf sop[3];
        int count;
@@ -171,37 +172,8 @@ PHP_FUNCTION(sem_get)
        max_acquire = 1;
        perm = 0666;
 
-       switch (ZEND_NUM_ARGS()) {
-               case 1:
-                       if (zend_get_parameters_ex(1, &arg_key)==FAILURE) {
-                               RETURN_FALSE;
-                       }
-                       convert_to_long_ex(arg_key);
-                       key = (int)Z_LVAL_PP(arg_key);
-                       break;
-               case 2:
-                       if (zend_get_parameters_ex(2, &arg_key, &arg_max_acquire)==FAILURE) {
-                               RETURN_FALSE;
-                       }
-                       convert_to_long_ex(arg_key);
-                       key = (int)Z_LVAL_PP(arg_key);
-                       convert_to_long_ex(arg_max_acquire);
-                       max_acquire = (int)Z_LVAL_PP(arg_max_acquire);
-                       break;
-               case 3:
-                       if (zend_get_parameters_ex(3, &arg_key, &arg_max_acquire, &arg_perm)==FAILURE) {
-                               RETURN_FALSE;
-                       }
-                       convert_to_long_ex(arg_key);
-                       convert_to_long_ex(arg_max_acquire);
-                       convert_to_long_ex(arg_perm);
-                       key = (int)Z_LVAL_PP(arg_key);
-                       max_acquire = (int)Z_LVAL_PP(arg_max_acquire);
-                       perm = (int)Z_LVAL_PP(arg_perm);
-                       break;
-               default:
-                       WRONG_PARAM_COUNT;
-                       break;
+       if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|lll", &key, &max_acquire, &perm, &auto_release)) {
+               RETURN_FALSE;
        }
 
        /* Get/create the semaphore.  Note that we rely on the semaphores
@@ -298,6 +270,7 @@ PHP_FUNCTION(sem_get)
        sem_ptr->key   = key;
        sem_ptr->semid = semid;
        sem_ptr->count = 0;
+       sem_ptr->auto_release = auto_release;
 
        Z_LVAL_P(return_value) = zend_list_insert(sem_ptr, php_sysvsem_module.le_sem);
        Z_TYPE_P(return_value) = IS_LONG;
@@ -382,50 +355,53 @@ PHP_FUNCTION(sem_release)
 
 PHP_FUNCTION(sem_remove)
 {
-        pval **arg_id;
-        int id,type;
+       pval **arg_id;
+       int id,type;
        sysvsem_sem *sem_ptr;
 #if HAVE_SEMUN
        union semun un;
+       struct semid_ds buf;
 #endif
-        if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg_id) == FAILURE) {
-                WRONG_PARAM_COUNT;
-        }
-        convert_to_long_ex(arg_id);
 
-        id = Z_LVAL_PP(arg_id);
+       if(ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg_id) == FAILURE) {
+                       WRONG_PARAM_COUNT;
+       }
+       convert_to_long_ex(arg_id);
 
-        sem_ptr = (sysvsem_sem *) zend_list_find(id, &type);
+       id = Z_LVAL_PP(arg_id);
 
-        if (type!=php_sysvsem_module.le_sem) {
-                php_error(E_WARNING, "%d is not a SysV semaphore index", id);
-                RETURN_FALSE;
-        }
+       sem_ptr = (sysvsem_sem *) zend_list_find(id, &type);
+
+       if (type!=php_sysvsem_module.le_sem) {
+                       php_error(E_WARNING, "%d is not a SysV semaphore index", id);
+                       RETURN_FALSE;
+       }
 
 #if HAVE_SEMUN
-        if(semctl(sem_ptr->semid,NULL,IPC_STAT,un)<0) {
+       un.buf = &buf;
+       if(semctl(sem_ptr->semid, 0, IPC_STAT, &un) < 0) {
 #else
-       if(semctl(sem_ptr->semid,NULL,IPC_STAT,NULL)<0) {
+       if(semctl(sem_ptr->semid, 0, IPC_STAT, NULL) < 0) {
 #endif
-                php_error(E_WARNING, "%d is not a existing SysV Semaphore Id", id);
-                RETURN_FALSE;
-        }
+               php_error(E_WARNING, "%d is not a existing SysV Semaphore Id", id);
+               RETURN_FALSE;
+       }
 
 #if HAVE_SEMUN
-               if(semctl(sem_ptr->semid,NULL,IPC_RMID,un)<0) {
+       if(semctl(sem_ptr->semid, 0, IPC_RMID, &un) < 0) {
 #else
-               if(semctl(sem_ptr->semid,NULL,IPC_RMID,NULL)<0) {
+       if(semctl(sem_ptr->semid, 0, IPC_RMID, NULL) < 0) {
 #endif
-                php_error(E_WARNING, "sem_remove() failed for id %d: %s", id, strerror(errno));
-                RETURN_FALSE;
-        }
+               php_error(E_WARNING, "sem_remove() failed for id %d: %s", id, strerror(errno));
+               RETURN_FALSE;
+       }
        
        /* let release_sysvsem_sem know we have removed
         * the semaphore to avoid issues with releasing.
         */ 
 
        sem_ptr->count = -1;
-        RETURN_TRUE;
+       RETURN_TRUE;
 }
 
 /* }}} */