Hi,
I just ran into a situtation where I didn't want sem_acquire() to block
forever if the semaphore was already locked, but instead just return an
error condition. There didn't seem to be a way to do this in current PHP
API, so I wrote a patch for it.
I tried to write it in such a way that current scripts that use
sem_acquire() would not break.
The new sem_acquire signature is:
int sem_acquire (int sem_identifier [, int nowait])
If the nowait flag is specified, sem_acquire() will return false
immediately if it is unable to acquire the semaphore without blocking.
When sem_acquire() returns false, the nowait flag will be true if the
semaphore could not be acquired without blocking. The nowait flag will be
false if a "normal" sem_acquire() error occurred.
If sem_acquire() returns true, the value of nowait should be ignored.
The input value of nowait is ignored, and must be specified as a
reference. If the nowait flag is not specified, the behaviour of
sem_acquire is identical to the current PHP behaviour.
PHP code sample
------------------------
$nowait = 0; /* initialize the variable */
$id = sem_get(0xF00);
sem_acquire($id); /* lock */
/* lock again */
if (!sem_acquire($id, &$nowait)) {
if ($nowait) {
echo "Already locked.";
} else {
die("sem_acquire error occurred");
}
}
/* release the id */
sem_release($id);
------------------------
Below is the patch against PHP 4.0.4pl1.
Cheers,
Michael
--- php-4.0.4pl1.orig/ext/sysvsem/sysvsem.c Wed Oct 25 13:44:01 2000
+++ php-4.0.4pl1/ext/sysvsem/sysvsem.c Mon Jan 22 11:37:12 2001
@@ -283,8 +283,8 @@
static void php_sysvsem_semop(INTERNAL_FUNCTION_PARAMETERS, int acquire)
{
- pval **arg_id;
- int id, type;
+ pval **arg_id, **arg_nowait;
+ int id, type, nowait;
sysvsem_sem *sem_ptr;
struct sembuf sop;
@@ -295,7 +295,31 @@
}
convert_to_long_ex(arg_id);
id = (int)(*arg_id)->value.lval;
+ nowait = 0;
break;
+
+ case 2:
+ /* nowait flag is only allowed for sem_acquire */
+ if (!acquire) {
+ WRONG_PARAM_COUNT;
+ }
+ if (zend_get_parameters_ex(2, &arg_id, &arg_nowait)==FAILURE) {
+ RETURN_FALSE;
+ }
+
+ if (!ParameterPassedByReference(ht, 2)) {
+ php_error(E_WARNING, "nowait flag must be passed by
+reference.");
+ RETURN_FALSE;
+ }
+
+ convert_to_long_ex(arg_id);
+ convert_to_boolean_ex(arg_nowait);
+
+ id = (int)(*arg_id)->value.lval;
+ nowait = 1;
+ (int)(*arg_nowait)->value.lval = 0;
+ break;
+
default:
WRONG_PARAM_COUNT;
break;
@@ -315,13 +339,25 @@
sop.sem_num = SYSVSEM_SEM;
sop.sem_op = acquire ? -1 : 1;
sop.sem_flg = SEM_UNDO;
+ if (nowait) {
+ sop.sem_flg |= IPC_NOWAIT;
+ }
while (semop(sem_ptr->semid, &sop, 1) == -1) {
- if (errno != EINTR) {
- php_error(E_WARNING, "semop(%s) failed for key 0x%x: %s",
- acquire ? "acquire" : "release",
sem_ptr->key, strerror(errno));
- RETURN_FALSE;
- }
+ switch (errno) {
+ case EINTR:
+ break;
+ case EAGAIN:
+ if (nowait) {
+ (int)(*arg_nowait)->value.lval = 1; /* set nowait flag */
+ RETURN_FALSE;
+ }
+ /* fall through */
+ default:
+ php_error(E_WARNING, "semop(%s) failed for key 0x%x: %s",
+ acquire ? "acquire" : "release", sem_ptr->key,
+strerror(errno));
+ RETURN_FALSE;
+ }
}
sem_ptr->count -= acquire ? -1 : 1;
--
Michael Vines
Black Echo Systems Inc.
[EMAIL PROTECTED]
--
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]