This patch adds logic to make sure that waitqueue object actually
exists in queues map before it tries to dereference it.

The content of this patch was authored by Benoit Canet.

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
---
 linux.cc | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/linux.cc b/linux.cc
index 25d28ee..0256c31 100644
--- a/linux.cc
+++ b/linux.cc
@@ -54,7 +54,7 @@ extern "C" long gettid()
 // The __cxa_guard_* functions only call futex in the rare case of contention,
 // in fact so rarely that OSv existed for a year before anyone noticed futex
 // was missing. So the performance of this implementation is not critical.
-static std::unordered_map<void*, waitqueue> queues;
+static std::unordered_map<void*, std::shared_ptr<waitqueue>> queues;
 static mutex queues_mutex;
 enum {
     FUTEX_WAIT           = 0,
@@ -71,12 +71,16 @@ int futex(int *uaddr, int op, int val, const struct 
timespec *timeout,
     case FUTEX_WAIT:
         WITH_LOCK(queues_mutex) {
             if (*uaddr == val) {
-                waitqueue &q = queues[uaddr];
+                auto i = queues.find(uaddr);
+                if (i == queues.end()) {
+                    queues[uaddr] = std::make_shared<waitqueue>();
+                }
+                std::shared_ptr<waitqueue> q = queues[uaddr];
                 if (timeout) {
                     sched::timer tmr(*sched::thread::current());
                     tmr.set(std::chrono::seconds(timeout->tv_sec) +
                             std::chrono::nanoseconds(timeout->tv_nsec));
-                    sched::thread::wait_for(queues_mutex, tmr, q);
+                    sched::thread::wait_for(queues_mutex, tmr, *q);
                     // FIXME: testing if tmr was expired isn't quite right -
                     // we could have had both a wakeup and timer expiration
                     // racing. It would be more correct to check if we were
@@ -86,7 +90,7 @@ int futex(int *uaddr, int op, int val, const struct timespec 
*timeout,
                         return -1;
                     }
                 } else {
-                    q.wait(queues_mutex);
+                    q->wait(queues_mutex);
                 }
                 return 0;
             } else {
@@ -104,11 +108,11 @@ int futex(int *uaddr, int op, int val, const struct 
timespec *timeout,
             auto i = queues.find(uaddr);
             if (i != queues.end()) {
                 int waken = 0;
-                while( (val > waken) && !(i->second.empty()) ) {
-                    i->second.wake_one(queues_mutex);
+                while( (val > waken) && !(i->second->empty()) ) {
+                    i->second->wake_one(queues_mutex);
                     waken++;
                 }
-                if(i->second.empty()) {
+                if(i->second->empty()) {
                     queues.erase(i);
                 }
                 return waken;
-- 
2.7.4

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to