osutil: change locking mechanism
authorjihye424.kim <jihye424.kim@samsung.com>
Tue, 6 Sep 2016 07:21:51 +0000 (16:21 +0900)
committerjihye424.kim <jihye424.kim@samsung.com>
Thu, 8 Sep 2016 10:42:35 +0000 (19:42 +0900)
Change-Id: Ic78b188deff7d1a4809528c906a51e89fd7abfa9
Signed-off-by: jihye424.kim <jihye424.kim@samsung.com>
tizen/src/emulator.c
tizen/src/emulator_legacy.c
tizen/src/util/osutil-darwin.c
tizen/src/util/osutil-linux.c
tizen/src/util/osutil-win32.c
tizen/src/util/osutil.c
tizen/src/util/osutil.h

index a39f0de..8216832 100644 (file)
@@ -109,25 +109,8 @@ static void set_bin_path(char const *const exec_argv)
     set_bin_path_os(exec_argv);
 }
 
-static void check_vm_lock(void)
-{
-    check_vm_lock_os();
-}
-
-static void make_vm_lock(void)
-{
-    make_vm_lock_os();
-}
-
-static void remove_vm_lock(void)
-{
-    remove_vm_lock_os();
-}
-
 static void emulator_notify_exit(Notifier *notifier, void *data)
 {
-    remove_vm_lock();
-
     int i;
     for (i = 0; i < _qemu_argc; ++i) {
         g_free(_qemu_argv[i]);
@@ -304,8 +287,7 @@ const char *prepare_maru(const gchar * const kernel_cmdline)
 
 void prepare_maru_after_device_init(void)
 {
-    check_vm_lock();
-    make_vm_lock();
+    make_vm_lock_os();
     maru_device_hotplug_init();
     qemu_add_opts(&qemu_ecs_opts);
     start_ecs();
index c775b53..e08c021 100644 (file)
@@ -167,20 +167,6 @@ static void set_image_and_log_path(char *qemu_argv)
     strcat(log_path, LOGFILE);
 }
 
-static void remove_vm_lock(void)
-{
-    remove_vm_lock_os();
-}
-
-static void emulator_notify_exit(Notifier *notifier, void *data)
-{
-    remove_vm_lock();
-
-    INFO("Exit emulator...\n");
-}
-
-static Notifier emulator_exit = { .notify = emulator_notify_exit };
-
 static void redir_output(void)
 {
     FILE *fp;
@@ -295,7 +281,6 @@ int legacy_emulator_main(int argc, char * argv[], char **envp)
 
     INFO("Emulator start !!!\n");
     atexit(maru_atexit);
-    emulator_add_exit_notifier(&emulator_exit);
 
     extract_skin_info(_skin_argc, _skin_argv);
 
index dd71eaf..2ebc6c4 100644 (file)
@@ -1,14 +1,11 @@
 /*
- * Emulator
+ * ostuil
  *
- * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (C) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact:
  * SeokYeon Hwang <syeon.hwang@samsung.com>
  * MunKyu Im <munkyu.im@samsung.com>
- * GiWoong Kim <giwoong.kim@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- * HyunJun Son
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -34,9 +31,7 @@
   @brief    Collection of utilities for darwin
  */
 
-#include "emulator_common.h"
 #include "osutil.h"
-#include "emulator.h"
 #include "emul_state.h"
 #include "debug_ch.h"
 #include "maru_err_table.h"
 #error
 #endif
 
-#include <string.h>
-#include <unistd.h>
-#include <sys/shm.h>
 #include <sys/sysctl.h>
 #include <SystemConfiguration/SystemConfiguration.h>
 
 MULTI_DEBUG_CHANNEL(qemu, osutil);
 
-static int g_shmid;
+void make_vm_lock_os(void) {
+    make_vm_lock_posix();
+}
+
 static CFDictionaryRef proxySettings;
 
 static char *cfstring_to_cstring(CFStringRef str) {
@@ -79,47 +74,6 @@ static int cfnumber_to_int(CFNumberRef num) {
     return value;
 }
 
-void check_vm_lock_os(void)
-{
-    /* TODO: */
-}
-
-void make_vm_lock_os(void)
-{
-    char *shared_memory;
-    int base_port;
-    base_port = get_emul_vm_base_port();
-    g_shmid = shmget((key_t)base_port, getpagesize(), 0666|IPC_CREAT);
-    if (g_shmid == -1) {
-        ERR("shmget failed\n");
-        perror("osutil-darwin: ");
-        return;
-    }
-
-    shared_memory = shmat(g_shmid, (char *)0x00, 0);
-    if (shared_memory == (void *)-1) {
-        ERR("shmat failed\n");
-        perror("osutil-darwin: ");
-        return;
-    }
-    g_sprintf(shared_memory, "%s", get_drive_image_file());
-    INFO("shared memory key: %d, value: %s\n", base_port, (char *)shared_memory);
-
-    if (shmdt(shared_memory) == -1) {
-        ERR("shmdt failed\n");
-        perror("osutil-darwin: ");
-    }
-
-}
-
-void remove_vm_lock_os(void)
-{
-    if (shmctl(g_shmid, IPC_RMID, 0) == -1) {
-        ERR("shmctl failed\n");
-        perror("osutil-linux: ");
-    }
-}
-
 void set_bin_path_os(char const *const exec_argv)
 {
     gchar *file_name = NULL;
index 474c037..164e92c 100644 (file)
@@ -1,14 +1,11 @@
 /*
- * Emulator
+ * osutil
  *
- * Copyright (C) 2012 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (C) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact:
  * SeokYeon Hwang <syeon.hwang@samsung.com>
  * MunKyu Im <munkyu.im@samsung.com>
- * GiWoong Kim <giwoong.kim@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- * HyunJun Son
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
   @brief    Collection of utilities for linux
  */
 
-#include <png.h>
+#include "png.h"
 #include "osutil.h"
-#include "emulator.h"
 #include "emul_state.h"
 #include "debug_ch.h"
-#include "maru_err_table.h"
 #include "sdb.h"
 
 #ifndef CONFIG_LINUX
 #error
 #endif
-#include <string.h>
-#include <unistd.h>
-#include <sys/shm.h>
-#include <sys/ipc.h>
 #include <linux/version.h>
 #include <sys/utsname.h>
 #include <sys/sysinfo.h>
@@ -58,8 +49,6 @@
 
 MULTI_DEBUG_CHANNEL(emulator, osutil);
 
-static int g_shmid;
-static char *g_shared_memory;
 static int gproxytool = GSETTINGS;
 
 /* Getting proxy commands */
@@ -76,82 +65,9 @@ static const char* gproxycmds[][2] = {
     { "gconftool-2 -g /system/proxy/socks_port", "gsettings get org.gnome.system.proxy.socks port" },
 };
 
-void check_vm_lock_os(void)
-{
-    int shm_id;
-    void *shm_addr;
-    uint32_t port;
-    int val;
-    struct shmid_ds shm_info;
-
-    for (port = 26100; port < 26200; port += 10) {
-        shm_id = shmget((key_t)port, 0, 0);
-        if (shm_id != -1) {
-            shm_addr = shmat(shm_id, (void *)0, 0);
-            if ((void *)-1 == shm_addr) {
-                ERR("error occured at shmat()\n");
-                break;
-            }
-
-            val = shmctl(shm_id, IPC_STAT, &shm_info);
-            if (val != -1) {
-                INFO("count of process that use shared memory : %d\n",
-                    shm_info.shm_nattch);
-                if ((shm_info.shm_nattch > 0) &&
-                    g_strcmp0(get_drive_image_file(), (char *)shm_addr) == 0) {
-                    if (check_port_bind_listen(port + 1) > 0) {
-                        shmdt(shm_addr);
-                        continue;
-                    }
-                    shmdt(shm_addr);
-                    maru_register_exit_msg(MARU_EXIT_UNKNOWN,
-                                        "Can not execute this VM.\n"
-                                        "The same name is running now.");
-                    exit(0);
-                } else {
-                    shmdt(shm_addr);
-                }
-            }
-        }
-    }
-}
-
 void make_vm_lock_os(void)
 {
-    int base_port;
-
-    base_port = get_emul_vm_base_port();
-
-    g_shmid = shmget((key_t)base_port, getpagesize(), 0666|IPC_CREAT);
-    if (g_shmid == -1) {
-        ERR("shmget failed\n");
-        perror("osutil-linux: ");
-        return;
-    }
-
-    g_shared_memory = shmat(g_shmid, (char *)0x00, 0);
-    if (g_shared_memory == (void *)-1) {
-        ERR("shmat failed\n");
-        perror("osutil-linux: ");
-        return;
-    }
-
-    g_sprintf(g_shared_memory, "%s", get_drive_image_file());
-    INFO("shared memory key: %d value: %s\n",
-        base_port, (char *)g_shared_memory);
-
-    if (shmdt(g_shared_memory) == -1) {
-        ERR("shmdt failed\n");
-        perror("osutil-linux: ");
-    }
-}
-
-void remove_vm_lock_os(void)
-{
-    if (shmctl(g_shmid, IPC_RMID, 0) == -1) {
-        ERR("shmctl failed\n");
-        perror("osutil-linux: ");
-    }
+    make_vm_lock_posix();
 }
 
 void set_bin_path_os(char const *const exec_argv)
index 0a55dc0..e460011 100644 (file)
@@ -1,14 +1,11 @@
 /*
- * Emulator
+ * osutil
  *
- * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (C) 2012 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact:
  * SeokYeon Hwang <syeon.hwang@samsung.com>
  * MunKyu Im <munkyu.im@samsung.com>
- * GiWoong Kim <giwoong.kim@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- * HyunJun Son
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -34,7 +31,7 @@
   @brief    Collection of utilities for win32
  */
 
-#include <png.h>
+#include "png.h"
 #include "emulator_common.h"
 #include "osutil.h"
 #include "emulator.h"
 
 MULTI_DEBUG_CHANNEL (emulator, osutil);
 
-static HANDLE g_hMapFile;
-static char *g_pBuf;
+static HANDLE lock_file = INVALID_HANDLE_VALUE;
+static char *lock_filename = NULL;
 
 static char g_sdcard[256] = {0,};
 static sdcard_info info;
 static const char *pactempfile = ".autoproxy";
 
-void check_vm_lock_os(void)
+static void remove_vm_lock_os(void)
 {
-    uint32_t port;
-    char *base_port = NULL;
-    char *pBuf;
-    HANDLE hMapFile;
-
-    for (port = 26100; port < 26200; port += 10) {
-        base_port = g_strdup_printf("%d", port);
-        hMapFile = OpenFileMapping(FILE_MAP_READ, TRUE, base_port);
-        if (hMapFile == NULL) {
-            INFO("port %s is not used.\n", base_port);
-            continue;
-        } else {
-            pBuf = (char *)MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 50);
-            if (pBuf == NULL) {
-                ERR("Could not map view of file (%d).\n", GetLastError());
-                CloseHandle(hMapFile);
-            }
+    g_free(lock_filename);
+    lock_filename = NULL;
 
-            if (strcmp(pBuf, get_drive_image_file()) == 0) {
-                maru_register_exit_msg(MARU_EXIT_UNKNOWN,
-                    "Can not execute this VM.\n"
-                    "The same name is running now.");
-                UnmapViewOfFile(pBuf);
-                CloseHandle(hMapFile);
-                free(base_port);
-                exit(0);
-            } else {
-                UnmapViewOfFile(pBuf);
-            }
-        }
-
-        CloseHandle(hMapFile);
-        free(base_port);
-    }
-}
-
-void make_vm_lock_os(void)
-{
-    char *port_in_use;
-    char *shared_memory;
-    int base_port;
-
-    base_port = get_emul_vm_base_port();
-    shared_memory = g_strdup_printf("%s", get_drive_image_file());
-    port_in_use =  g_strdup_printf("%d", base_port);
-    g_hMapFile = CreateFileMapping(
-                 INVALID_HANDLE_VALUE, /* use paging file */
-                 NULL,                 /* default security */
-                 PAGE_READWRITE,       /* read/write access */
-                 0,                /* maximum object size (high-order DWORD) */
-                 50,               /* maximum object size (low-order DWORD) */
-                 port_in_use);         /* name of mapping object */
-    if (g_hMapFile == NULL) {
-        ERR("Could not create file mapping object (%d).\n", GetLastError());
+    if (lock_file == INVALID_HANDLE_VALUE) {
         return;
     }
 
-    g_pBuf = MapViewOfFile(g_hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 50);
-    if (g_pBuf == NULL) {
-        ERR("Could not map view of file (%d).\n", GetLastError());
-        CloseHandle(g_hMapFile);
-        return;
-    }
+    CloseHandle(lock_file);
+    lock_file = INVALID_HANDLE_VALUE;
+}
 
-    CopyMemory((PVOID)g_pBuf, shared_memory, strlen(shared_memory));
-    free(port_in_use);
-    free(shared_memory);
+static void notify_remove_lock(Notifier *notifier, void *data)
+{
+    remove_vm_lock_os();
 }
 
-void remove_vm_lock_os(void)
+static Notifier remove_lock = { .notify = notify_remove_lock };
+
+/*
+On Windows, emulator will stop before checking lock because platform
+image file and kernel log file are aleady opened with exclusive write
+lock by pre-executed emulator. But it is still useful for
+emulator-manager.
+*/
+void make_vm_lock_os(void)
 {
-    if (g_pBuf != NULL) {
-        UnmapViewOfFile(g_pBuf);
+    g_assert(lock_file == INVALID_HANDLE_VALUE);
+    g_assert(lock_filename == NULL);
+
+    lock_filename = g_strdup_printf("%s.lock", get_drive_image_file());
+
+    if (g_mkdir_with_parents(g_path_get_dirname(lock_filename), 0777)) {
+        ERR("Can not create directory for lock file: %ld\n",
+                    GetLastError());
     }
-    if (g_hMapFile != NULL) {
-        CloseHandle(g_hMapFile);
+    lock_file = CreateFile(lock_filename,
+                           GENERIC_READ | GENERIC_WRITE,
+                           0,       // No share
+                           NULL,
+                           CREATE_ALWAYS,
+                           FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
+                           NULL);
+    if (lock_file == INVALID_HANDLE_VALUE) {
+        DWORD error = GetLastError();
+        // On Windows, the file opened by CreateFile has exclusive lock
+        // naturally unless FILE_SHARE_* attribute is set.
+        if (error == ERROR_SHARING_VIOLATION) {
+            maru_register_exit_msg(MARU_EXIT_UNKNOWN,
+                    "Can not execute this VM.\n"
+                    "The same VM may be running now.");
+            exit(1);
+        }
+
+        ERR("Failed to create lock file: %0xlx\n", error);
     }
-}
 
+    emulator_add_exit_notifier(&remove_lock);
+}
 
 void set_bin_path_os(char const *const exec_argv)
 {
index 240b31f..e8a3a5d 100644 (file)
@@ -1,14 +1,11 @@
 /*
- * Emulator
+ * osutil
  *
- * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (C) 2012-2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact:
  * SeokYeon Hwang <syeon.hwang@samsung.com>
  * MunKyu Im <munkyu.im@samsung.com>
- * GiWoong Kim <giwoong.kim@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- * HyunJun Son
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 MULTI_DEBUG_CHANNEL(emulator, osutil);
 
 #ifndef CONFIG_WIN32
+
+#include "emulator.h"
+#include "emul_state.h"
+#include "maru_err_table.h"
+
+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;
 #endif
 const char *pac_tempfile = ".autoproxy";
@@ -124,6 +134,95 @@ static int fd_unlock(int fd)
     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) {
+        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 {
+        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)
+{
+    if (lock_file == -1) {
+        return;
+    }
+
+    if (fd_unlock(lock_file)) {
+        INFO("Failed to remove lock from lock file");
+    }
+    close(lock_file);
+
+    lock_file = -1;
+}
+
+static void notify_remove_lock(Notifier *notifier, void *data)
+{
+    remove_vm_lock_posix();
+}
+
+static Notifier remove_lock = { .notify = notify_remove_lock };
+
+void make_vm_lock_posix(void)
+{
+    const char *image_file = get_drive_image_file();
+    int error = 0;
+
+    g_assert(lock_file == -1);
+    g_assert(image_file != NULL);
+
+retry:
+    lock_file = open(image_file, O_RDWR);
+    if (lock_file == -1) {
+        error = errno;
+        ERR("Failed to open image file for lock: %s\n",
+            strerror(error));
+        return;
+    }
+
+    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);
+                INFO("Try to lock again after sleep\n");
+                g_usleep(10000);        /* 10 msec */
+                goto retry;
+            }
+            maru_register_exit_msg(MARU_EXIT_UNKNOWN,
+                        "Can not execute this VM.\n"
+                        "The same name is running now.");
+            exit(1);
+        }
+
+        ERR("Failed to lock image file: %s\n", strerror(error));
+        close(lock_file);
+        lock_file = -1;
+        return;
+    }
+
+    emulator_add_exit_notifier(&remove_lock);
+}
+
 inline bool make_sdcard_lock_posix(char *sdcard)
 {
     char *lock_file = g_strdup_printf("%s.lck", sdcard);
index 33de9c9..ce63254 100644 (file)
@@ -1,14 +1,11 @@
 /*
- * Emulator
+ * osutil
  *
- * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (C) 2012-2016 Samsung Electronics Co., Ltd. All rights reserved.
  *
  * Contact:
  * SeokYeon Hwang <syeon.hwang@samsung.com>
  * MunKyu Im <munkyu.im@samsung.com>
- * GiWoong Kim <giwoong.kim@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
- * HyunJun Son
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 
 #include "qemu-common.h"
 
+#ifdef CONFIG_WIN32
+#include "sysemu/os-win32.h"
+#else
+#include "sysemu/os-posix.h"
+#endif
+
 #define HTTP_PROTOCOL "http="
 #define HTTP_PREFIX "http://"
 #define HTTPS_PROTOCOL "https="
@@ -64,9 +67,7 @@
 
 extern const char *pac_tempfile;
 
-void check_vm_lock_os(void);
 void make_vm_lock_os(void);
-void remove_vm_lock_os(void);
 bool make_sdcard_lock_os(char *sdcard);
 int remove_sdcard_lock_os(char *sdcard);
 
@@ -83,6 +84,8 @@ typedef struct sdcard_info
 
 
 #ifndef CONFIG_WIN32
+void make_vm_lock_posix(void);
+
 bool make_sdcard_lock_posix(char *sdcard);
 int remove_sdcard_lock_posix(char *sdcard);
 #endif