Hi Yann,
Am 25.03.2015 um 09:56 schrieb Yann Ylavic:
>> To mitigate that design flaw I would provide the timeout by reference
>> and update it by the functions using it. This has also the nice benefit
>> that the caller is able to retrieve the time it needed to wait.
>
> By doing so, you have to get the current time (call apr_time_now())
> each time, and I wanted to avoid it when the native functions don't
> need it.
> The remaining time is not important if you can pass an absolute time (IMHO).
Ok, understood. You're right.
Sorry, took me a while to give your patch a try. As the patch didn't
apply cleanly to trunk (ie. SVN rev. 1676013), I assume that it is
already applied in trunk. So I went ahead without applying your patch.
Is this correct?
I wrote a small test program that should prove me that timed global
locks work across process boundaries (see attached source). But for some
reason apr_global_mutex_unlock() return 1 if called in the child
process. This is the output that I get from the compiled test program:
Trying to get locked mutex... timed out after 1 second (expected)
Child trying to unlock the mutex got 1 (unexpected)
Trying to get locked mutex... timed out after 2 seconds (unexpected)
Did I do anything wrong?
Best regards,
Micha
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <apr.h>
#include <apr_pools.h>
#include <apr_global_mutex.h>
#define LOCKFILE "/tmp/apr-synctest-lockfile"
int main(int argc, const char *argv[]) {
apr_pool_t *pool = NULL;
apr_global_mutex_t *mutex = NULL;
apr_time_t timeout;
apr_status_t rv;
pid_t child;
int child_rc;
int rc = 0;
assert(apr_initialize() == APR_SUCCESS);
assert(apr_pool_create(&pool, NULL) == APR_SUCCESS);
apr_global_mutex_create(&mutex, LOCKFILE, APR_LOCK_DEFAULT_TIMED, pool);
/*********************************************************
* LOCK
*********************************************************/
apr_global_mutex_lock(mutex);
timeout = apr_time_from_sec(1);
printf("Trying to get locked mutex...");
rv = apr_global_mutex_timedlock(mutex, timeout, 0);
if (rv == APR_TIMEUP) {
printf(" timed out after 1 second (expected)\n");
} else {
printf(" FAILED: %d (unexpected)\n", rv);
rc = 1;
goto cleanup;
}
child = fork();
if (child == 0) { // child process
assert(apr_global_mutex_child_init(&mutex, LOCKFILE, pool) == APR_SUCCESS);
(void)sleep(1);
/*********************************************************
* UNLOCK in forked child
*********************************************************/
rv = apr_global_mutex_unlock(mutex);
if (rv != APR_SUCCESS) {
rc = 1;
printf("Child trying to unlock the mutex got %d (unexpected)\n", rv);
}
} else if (child > 0) { // parent process
timeout = apr_time_from_sec(2);
printf("Trying to get locked mutex...");
rv = apr_global_mutex_timedlock(mutex, timeout, 0);
if (rv == APR_SUCCESS) {
printf(" OK (expected)\n");
} else if (rv == APR_TIMEUP) {
printf(" timed out after 2 seconds (unexpected)\n");
rc = 1;
} else {
printf(" FAILED: %d (unexpected)\n", rv);
rc = 1;
}
wait(&child_rc);
if (rc == 0)
rc = child_rc;
} else { // fork() failed
printf("failed to fork(): %m");
rc = 1;
goto cleanup;
}
cleanup:
apr_pool_destroy(pool);
apr_terminate();
return rc;
}