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);
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);