Linux: TransportRpmsg: Fix Mutex Deadlock Issue
authorAngela Stegmaier <angelabaker@ti.com>
Thu, 3 Aug 2017 21:16:01 +0000 (16:16 -0500)
committerAngela Stegmaier <angelabaker@ti.com>
Wed, 13 Sep 2017 21:26:29 +0000 (16:26 -0500)
In an error recovery situation, it is possible that a
mutex deadlock could occur when MessageQ_delete happened
at the same time that an fd was being signaled about the
remote core error in the same process. This error could
occur if there are multiple MessageQs in the same process
communicating with the remote core that is doing recovery.

When MessageQ_delete grabs the lock, it then tries to
communicate with rpmsgThreadFxn, sending a message and
then waiting for a response. If at the same time, the thread
is processing a shutdown notification for an fd, it will
also try to grab the mutex, but will be blocked because
MessageQ_delete is holding the mutex. The rpmsgThreadFxn
will not continue until it gets the mutex, leading to the
deadlock.

The fix is to change the mutex_lock to a trylock when
handling shutdown notifications in rpmsgThreadFxn. If the
thread fails to acquire the lock, it continues processing
commands and will try again later to process the shutdown
request at a time when the lock is no longer being held.

Signed-off-by: Angela Stegmaier <angelabaker@ti.com>
linux/src/transport/TransportRpmsg.c

index c236e200296ab67ad0a6e417b6879cc7201c26a1..2a6abe32a3ec2f588b32d8f265248f7ab1f747aa 100644 (file)
@@ -556,7 +556,13 @@ void *rpmsgThreadFxn(void *arg)
                             "rpmsgThreadFxn: transportGet failed on fd %d, "
                             "returned %d\n", fd, tmpStatus);
 
-                    pthread_mutex_lock(&TransportRpmsg_module->gate);
+                    retval = pthread_mutex_trylock(&TransportRpmsg_module->gate);
+                    if (retval != 0) {
+                        printf("Warning: rpmsgThreadFxn: "
+                               "unable to get the lock during shutdown, "
+                               "will try again\n");
+                        continue;
+                    }
 
                     /*
                      * Don't close(fd) at this time since it will get closed