osutil: modified posix lock mechanism
authorSangho Park <sangho.p@samsung.com>
Wed, 27 Jan 2016 09:09:37 +0000 (18:09 +0900)
committerSangho Park <sangho.p@samsung.com>
Thu, 28 Jan 2016 02:23:49 +0000 (11:23 +0900)
After failing to lock file, check the lock whether other emulator locks
the file or not. If other emulator does not lock the file, try again to
lock file after sleep.

Change-Id: I9cfc3c4af395eb0d9e113eefb83d3953b431a19c
Signed-off-by: Sangho Park <sangho.p@samsung.com>
tizen/src/util/osutil.c

index 2c13652..442d123 100644 (file)
@@ -46,35 +46,56 @@ DECLARE_DEBUG_CHANNEL(osutil)
 
 
 static int lock_file = -1;
+static struct flock _lock = {
+    .l_type = F_WRLCK,
+    .l_start = 0,
+    .l_whence = SEEK_SET,
+    .l_len = 0,
+};
 
 static sdcard_info info;
 
 static int fd_lock(int fd)
 {
-    struct flock lock;
-
-    lock.l_type = F_WRLCK;
-    lock.l_start = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len = 0;
-    lock.l_pid = getpid();
-
-    return fcntl(fd, F_SETLK, &lock);
+    return fcntl(fd, F_SETLK, &_lock);
 }
 
 static int fd_unlock(int fd)
 {
-    struct flock lock;
-
-    lock.l_type = F_UNLCK;
-    lock.l_start = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len = 0;
-    lock.l_pid = getpid();
-
+    struct flock lock = {
+        .l_type = F_UNLCK,
+        .l_start = _lock.l_start,
+        .l_whence = _lock.l_whence,
+        .l_len = _lock.l_len,
+    };
     return fcntl(fd, F_SETLK, &lock);
 }
 
+/*
+ * Check the file lock.
+ * Emulator locks the whole file exclusively. If one of the current lock's
+ * l_type, l_start, l_whence, and l_len is different from my own, other
+ * but emulator locks the file and then we will try to lock the file.
+ */
+static bool fd_checklock(int fd)
+{
+    struct flock lock = _lock;
+
+    if (fcntl(fd, F_GETLK, &lock) < 0) {
+        LOG_INFO("Failed to get lock information: %s\n", strerror(errno));
+    } else if (lock.l_type == _lock.l_type &&
+               lock.l_start == _lock.l_start &&
+               lock.l_whence == _lock.l_whence &&
+               lock.l_len == _lock.l_len) {
+        return true;
+    } else {
+        LOG_INFO("Lock: type=%d(%d), start=%d, whence=%d, len=%d, pid=%d\n",
+                 lock.l_type, _lock.l_type, (int)lock.l_start, lock.l_whence,
+                 (int)lock.l_len, lock.l_pid);
+    }
+    return false;
+}
+
 static void remove_vm_lock_posix(void)
 {
     g_assert(lock_file != -1);
@@ -94,40 +115,42 @@ static void notify_remove_lock(Notifier *notifier, void *data)
 
 static Notifier remove_lock = { .notify = notify_remove_lock };
 
-#define RETRY_COUNT 10
 void make_vm_lock_posix(void)
 {
     const char *image_file = get_drive_image_file();
-    int error = 0, i;
+    int error = 0;
 
     g_assert(lock_file == -1);
     g_assert(image_file != NULL);
 
-    for (i = 0; i < RETRY_COUNT; ++i) {
-        lock_file = open(image_file, O_RDWR);
-        if (lock_file == -1) {
-            error = errno;
-            LOG_WARNING("Failed to open image file for lock: %s\n",
+retry:
+    lock_file = open(image_file, O_RDWR);
+    if (lock_file == -1) {
+        error = errno;
+        LOG_WARNING("Failed to open image file for lock: %s\n",
                     strerror(error));
-            return;
-        }
+        return;
+    }
 
-        if (fd_lock(lock_file) == -1) {
-            error = errno;
-            if (error == EAGAIN || error == EACCES) {
-                if (i == RETRY_COUNT - 1) {
-                    error_report("Can not execute this VM. "
-                            "The same VM may be running now.");
-                    exit(1);
-                }
-                g_usleep(10000);    /* 10 msec */
+    if (fd_lock(lock_file) == -1) {
+        error = errno;
+        if (error == EAGAIN || error == EACCES) {
+            /* Check whether other except emulator locks the file */
+            if (fd_checklock(lock_file) == false) {
+                close(lock_file);
+                LOG_INFO("Try to lock again after sleep\n");
+                g_usleep(10000);        /* 10 msec */
+                goto retry;
             }
-
-            LOG_WARNING("Failed to lock image file: %s\n", strerror(error));
-            close(lock_file);
-            lock_file = -1;
-            return;
+            error_report("Can not execute this VM. "
+                         "The same VM may be running now.");
+            exit(1);
         }
+
+        LOG_WARNING("Failed to lock image file: %s\n", strerror(error));
+        close(lock_file);
+        lock_file = -1;
+        return;
     }
 
     emulator_add_exit_notifier(&remove_lock);