Archived

This forum has been archived. Please start a new discussion on GitHub.

return value of pthread_mutex_trylock() not check properly

I'm trying to get Ice working under FreeBSD.

It builds fine but make test fails:
running mutex test... ../../../include/IceUtil/Mutex.h:323: IceUtil::ThreadSyscallException:
thread syscall exception: Resource deadlock avoided failed
test mutex failed

After some investigation it turned out that in Mutex.h the return value of pthread_mutex_trylock() is tested against EBUSY. But the new threading library in FreeBSD returns EDEADLK (which seems to be okay according to the standard).

This simple patch solves the problem:
--- include/IceUtil/Mutex.h.orig        Sun May 23 23:52:37 2004
+++ include/IceUtil/Mutex.h     Sun May 23 23:54:30 2004
@@ -318,7 +318,7 @@
 Mutex::tryLock() const
 {
     int rc = pthread_mutex_trylock(&_mutex);
-    if(rc != 0 && rc != EBUSY)
+    if(rc != 0 && rc != EBUSY && rc != EDEADLK)
     {
        throw ThreadSyscallException(__FILE__, __LINE__, rc);
     }

Exactly the same problem occurs in StaticMutex.h.

After patching both header files make test just works fine.

Comments

  • mes
    mes California
    Welcome to the forum!

    If Mutex::tryLock receives EDEADLK, it indicates an application error because it means an application thread is attempting to recursively lock a non-recursive mutex. It is appropriate for an exception to be raised in this case.

    So, either there is a bug in the test suite, or the FreeBSD threading library is misbehaving. Can you build Ice in debug mode and provide a stack trace of the test failure? Note that you can run the test directly by executing test/IceUtil/thread/client.

    Thanks,
    - Mark
  • Unfortunately gdb has troubles with the threading library and I'm unable to get a backtrace.

    I put in some debug information to track the failing test down:

    This is around line 126 in MutexTest.cpp:
    Mutex::TryLock lock2(mutex); std::cerr << "this get's printed\n";
    test(lock.tryAcquire() == false); std::cerr << "we never reach this\n";
    

    The return value of pthread_mutex_trylock() in Mutex.h is EDEADLK with the new threading library (it was EBUSY with the old one) which causes the ThreadSyscallException to be thrown.

    Sorry again that I can't provide a backtrace but I hope this is information somewhat useful to you.
  • mes
    mes California
    Ok, now I strongly suspect a bug in the FreeBSD threading library you are using.

    The C equivalent of the test to this point is pretty simple:
    pthread_mutex_init(...);
    pthread_mutex_lock(...);
    pthread_mutex_unlock(...);
    pthread_mutex_trylock(...);
    
    The call to trylock should not be returning EDEADLK in this case, since the mutex has clearly been unlocked.

    Perhaps you should submit this test to the FreeBSD folks as a bug report.

    Take care,
    - Mark
  • mes
    mes California
    Please ignore my previous reply. A colleague graciously pointed out that I was quite wrong. Thanks Benoit. ;)

    It appears from this link that pthread_mutex_trylock on FreeBSD raises EDEADLK in some circumstances and EBUSY in others.

    At this point we would prefer not to mask the EDEADLK result by modifying Mutex::tryLock as you suggested, so we will modify the tests to trap IceUtil::ThreadSyscallException and check the result code.

    Thanks,
    - Mark
  • Thanks for your quick replies and the inclusion of the fixes in Ice 1.4.

    Unfortunately I missed that the monitor<mutex> test fails just for the same reason (because it was obscured by my Mutex.h patch).

    The failing code is test/IceUtil/thread/MonitorMutexTest.cpp, line 111:
    Monitor<Mutex>::TryLock tlock(monitor);
    

    Would be great if this could be integrated too for later releases.