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; }