FIX #2398: file locking wasn't thread-safe
authorSimon Marlow <marlowsd@gmail.com>
Fri, 4 Jul 2008 14:46:26 +0000 (14:46 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Fri, 4 Jul 2008 14:46:26 +0000 (14:46 +0000)
rts/posix/FileLock.c

index 8d25820..e871be5 100644 (file)
@@ -10,6 +10,7 @@
 #include "Hash.h"
 #include "FileLock.h"
 #include "RtsUtils.h"
+#include "OSThreads.h"
 
 #include <unistd.h>
 #include <sys/stat.h>
@@ -28,6 +29,10 @@ typedef struct {
 static HashTable *obj_hash;
 static HashTable *fd_hash;
 
+#ifdef THREADED_RTS
+static Mutex file_lock_mutex;
+#endif
+
 static int cmpLocks(StgWord w1, StgWord w2)
 {
     Lock *l1 = (Lock *)w1;
@@ -67,6 +72,8 @@ lockFile(int fd, dev_t dev, ino_t ino, int for_writing)
 {
     Lock key, *lock;
 
+    ACQUIRE_LOCK(&file_lock_mutex);
+
     key.device = dev;
     key.inode  = ino;
 
@@ -80,16 +87,19 @@ lockFile(int fd, dev_t dev, ino_t ino, int for_writing)
         lock->readers = for_writing ? -1 : 1;
         insertHashTable(obj_hash, (StgWord)lock, (void *)lock);
         insertHashTable(fd_hash, fd, lock);
+        RELEASE_LOCK(&file_lock_mutex);
         return 0;
     }
     else
     {
         // single-writer/multi-reader locking:
         if (for_writing || lock->readers < 0) {
+            RELEASE_LOCK(&file_lock_mutex);
             return -1;
         }
         insertHashTable(fd_hash, fd, lock);
         lock->readers++;
+        RELEASE_LOCK(&file_lock_mutex);
         return 0;
     }
 }
@@ -99,11 +109,14 @@ unlockFile(int fd)
 {
     Lock *lock;
 
+    ACQUIRE_LOCK(&file_lock_mutex);
+
     lock = lookupHashTable(fd_hash, fd);
     if (lock == NULL) {
         // errorBelch("unlockFile: fd %d not found", fd); 
         // This is normal: we didn't know when calling unlockFile
         // whether this FD referred to a locked file or not.
+        RELEASE_LOCK(&file_lock_mutex);
         return 1;
     }
 
@@ -118,5 +131,7 @@ unlockFile(int fd)
         stgFree(lock);
     }
     removeHashTable(fd_hash, fd, NULL);
+
+    RELEASE_LOCK(&file_lock_mutex);
     return 0;
 }