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

Reply via email to