From d54de811d2fd4b9021aa7e560a93f9925d0dbc96 Mon Sep 17 00:00:00 2001 From: "jihye424.kim" Date: Tue, 6 Sep 2016 16:21:51 +0900 Subject: [PATCH] osutil: change locking mechanism Change-Id: Ic78b188deff7d1a4809528c906a51e89fd7abfa9 Signed-off-by: jihye424.kim --- tizen/src/emulator.c | 20 +---- tizen/src/emulator_legacy.c | 15 ---- tizen/src/util/osutil-darwin.c | 58 ++------------- tizen/src/util/osutil-linux.c | 92 +---------------------- tizen/src/util/osutil-win32.c | 130 ++++++++++++++------------------- tizen/src/util/osutil.c | 109 +++++++++++++++++++++++++-- tizen/src/util/osutil.h | 17 +++-- 7 files changed, 178 insertions(+), 263 deletions(-) diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index a39f0de502..8216832992 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -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(); diff --git a/tizen/src/emulator_legacy.c b/tizen/src/emulator_legacy.c index c775b5320f..e08c0210cb 100644 --- a/tizen/src/emulator_legacy.c +++ b/tizen/src/emulator_legacy.c @@ -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); diff --git a/tizen/src/util/osutil-darwin.c b/tizen/src/util/osutil-darwin.c index dd71eaf46a..2ebc6c4fa1 100644 --- a/tizen/src/util/osutil-darwin.c +++ b/tizen/src/util/osutil-darwin.c @@ -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 * MunKyu Im - * GiWoong Kim - * YeongKyoon Lee - * 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" @@ -46,15 +41,15 @@ #error #endif -#include -#include -#include #include #include 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; diff --git a/tizen/src/util/osutil-linux.c b/tizen/src/util/osutil-linux.c index 474c037f7b..164e92c960 100644 --- a/tizen/src/util/osutil-linux.c +++ b/tizen/src/util/osutil-linux.c @@ -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 * MunKyu Im - * GiWoong Kim - * YeongKyoon Lee - * 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,21 +31,15 @@ @brief Collection of utilities for linux */ -#include +#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 -#include -#include -#include #include #include #include @@ -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) diff --git a/tizen/src/util/osutil-win32.c b/tizen/src/util/osutil-win32.c index 0a55dc03ba..e460011f77 100644 --- a/tizen/src/util/osutil-win32.c +++ b/tizen/src/util/osutil-win32.c @@ -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 * MunKyu Im - * GiWoong Kim - * YeongKyoon Lee - * 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 +#include "png.h" #include "emulator_common.h" #include "osutil.h" #include "emulator.h" @@ -51,94 +48,73 @@ 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) { diff --git a/tizen/src/util/osutil.c b/tizen/src/util/osutil.c index 240b31f218..e8a3a5d186 100644 --- a/tizen/src/util/osutil.c +++ b/tizen/src/util/osutil.c @@ -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 * MunKyu Im - * GiWoong Kim - * YeongKyoon Lee - * HyunJun Son * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -43,6 +40,19 @@ 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); diff --git a/tizen/src/util/osutil.h b/tizen/src/util/osutil.h index 33de9c9e01..ce63254a9c 100644 --- a/tizen/src/util/osutil.h +++ b/tizen/src/util/osutil.h @@ -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 * MunKyu Im - * GiWoong Kim - * YeongKyoon Lee - * 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,6 +31,12 @@ #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 -- 2.34.1