aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2022-12-10 01:18:35 +0100
committerdec05eba <dec05eba@protonmail.com>2022-12-10 01:18:35 +0100
commit247d83b1eaa64dd28900f90763dd02e71d5bd3f6 (patch)
tree5cadfb67d35ce72985b952b3e7e83d9d40335d4d
parent3481b4aa4db2d8af1c6d5820010acbed76323890 (diff)
Matrix: use unix domain socket for unique process file instead
-rw-r--r--plugins/utils/UniqueProcess.hpp6
-rw-r--r--src/plugins/utils/UniqueProcess.cpp154
2 files changed, 79 insertions, 81 deletions
diff --git a/plugins/utils/UniqueProcess.hpp b/plugins/utils/UniqueProcess.hpp
index a2145f9..f85704f 100644
--- a/plugins/utils/UniqueProcess.hpp
+++ b/plugins/utils/UniqueProcess.hpp
@@ -1,7 +1,7 @@
#pragma once
namespace QuickMedia {
- bool is_quickmedia_instance_already_running(const char *pid_file_dir, const char *plugin_name);
- bool set_quickmedia_instance_unique(const char *pid_file_dir, const char *plugin_name);
- void remove_quickmedia_instance_lock(const char *pid_file_dir, const char *plugin_name);
+ bool is_quickmedia_instance_already_running(const char *sock_file_dir, const char *plugin_name);
+ bool set_quickmedia_instance_unique(const char *sock_file_dir, const char *plugin_name);
+ void remove_quickmedia_instance_lock(const char *sock_file_dir, const char *plugin_name);
} \ No newline at end of file
diff --git a/src/plugins/utils/UniqueProcess.cpp b/src/plugins/utils/UniqueProcess.cpp
index 76b9cb1..d2025f5 100644
--- a/src/plugins/utils/UniqueProcess.cpp
+++ b/src/plugins/utils/UniqueProcess.cpp
@@ -1,113 +1,111 @@
#include "../../../plugins/utils/UniqueProcess.hpp"
+#include "../../../include/Storage.hpp"
#include <stdio.h>
-#include <string.h>
#include <limits.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
-#include <stdlib.h>
+#include <errno.h>
namespace QuickMedia {
- static bool is_process_running_program(pid_t pid, const char *program_name) {
- char filepath[256];
- snprintf(filepath, sizeof(filepath), "/proc/%ld/cmdline", (long)pid);
+ bool is_quickmedia_instance_already_running(const char *sock_file_dir, const char *plugin_name) {
+ char sock_file[PATH_MAX];
+ snprintf(sock_file, sizeof(sock_file), "%s/quickmedia.%s.sock", sock_file_dir, plugin_name);
- int fd = open(filepath, O_RDONLY);
- if(fd == -1)
+ std::string resolved_path;
+ if(file_get_content(sock_file, resolved_path) != 0)
return false;
- char buffer[PATH_MAX + 1];
- ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
- if(bytes_read == -1) {
- close(fd);
- return false;
- }
- buffer[bytes_read] = '\0';
+ resolved_path.resize(108); // sizeof(addr.sun_path) is 108
- char resolved_path[PATH_MAX + 1];
- if(!realpath(buffer, resolved_path)) {
- close(fd);
- return false;
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ fprintf(stderr, "Error: failed to create unix domain socket, error: %s\n", strerror(errno));
+ return true;
}
- bytes_read = strlen(resolved_path);
- resolved_path[bytes_read] = '\0';
- const char *end = resolved_path + bytes_read;
- const char *start = (const char*)memrchr(resolved_path, '/', bytes_read);
- if(start)
- start += 1;
- else
- start = buffer;
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
- const size_t cmd_arg0_len = end - start;
- const size_t program_name_len = strlen(program_name);
- bool running = (cmd_arg0_len == program_name_len && memcmp(start, program_name, program_name_len) == 0);
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, resolved_path.c_str());
+
+ bool running = connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0;
+ int err = errno;
+ if(err == EAGAIN)
+ running = true;
+ else if(err == ENOENT)
+ running = false;
close(fd);
return running;
}
- bool is_quickmedia_instance_already_running(const char *pid_file_dir, const char *plugin_name) {
- char pid_file[PATH_MAX];
- snprintf(pid_file, sizeof(pid_file), "%s/quickmedia.%s.pid", pid_file_dir, plugin_name);
+ bool set_quickmedia_instance_unique(const char *sock_file_dir, const char *plugin_name) {
+ char socket_file[] = "/tmp/quickmedia.XXXXXX";
+ int tmp_file_fd = mkstemp(socket_file);
+ if(tmp_file_fd == -1) {
+ fprintf(stderr, "Error: failed to create temporary file for unix domain socket, error: %s\n", strerror(errno));
+ return false;
+ }
+ unlink(socket_file);
+ close(tmp_file_fd);
- char buffer[256];
- int fd = open(pid_file, O_RDONLY);
- if(fd == -1)
+ int fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(fd == -1) {
+ fprintf(stderr, "Error: failed to create unix domain socket, error: %s\n", strerror(errno));
return false;
+ }
- ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
- if(bytes_read < 0) {
- perror("failed to read quickmedia pid file");
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, socket_file);
+
+ if(bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ fprintf(stderr, "Error: failed to bind unix domain socket, error: %s\n", strerror(errno));
+ unlink(socket_file);
close(fd);
return false;
}
- buffer[bytes_read] = '\0';
- close(fd);
- bool running = false;
- long pid = 0;
- if(sscanf(buffer, "%ld", &pid) == 1) {
- if(is_process_running_program(pid, "quickmedia")) {
- fprintf(stderr, "Error: quickmedia %s is already running\n", plugin_name);
- running = true;
- }
- } else {
- fprintf(stderr, "Warning: quickmedia pid file is in incorrect format, it's possible that its corrupt. Replacing file and continuing...\n");
- running = false;
+ if(listen(fd, 0) == -1) {
+ fprintf(stderr, "Error: failed to listen to unix domain socket, error: %s\n", strerror(errno));
+ unlink(socket_file);
+ close(fd);
+ return false;
}
- if(!running)
- unlink(pid_file);
-
- return running;
+ char sock_file[PATH_MAX];
+ snprintf(sock_file, sizeof(sock_file), "%s/quickmedia.%s.sock", sock_file_dir, plugin_name);
+ bool success = file_overwrite(sock_file, socket_file) == 0;
+ if(!success) {
+ fprintf(stderr, "Error: failed to create %s unix domain socket link file\n", sock_file);
+ unlink(socket_file);
+ close(fd);
+ }
+ return success;
}
- bool set_quickmedia_instance_unique(const char *pid_file_dir, const char *plugin_name) {
- char pid_file[PATH_MAX];
- snprintf(pid_file, sizeof(pid_file), "%s/quickmedia.%s.pid", pid_file_dir, plugin_name);
+ void remove_quickmedia_instance_lock(const char *sock_file_dir, const char *plugin_name) {
+ char sock_file[PATH_MAX];
+ snprintf(sock_file, sizeof(sock_file), "%s/quickmedia.%s.sock", sock_file_dir, plugin_name);
- int fd = open(pid_file, O_WRONLY|O_CREAT|O_TRUNC, 0777);
- if(fd == -1) {
- perror("failed to create quickmedia pid file");
- return false;
+ std::string resolved_path;
+ if(file_get_content(sock_file, resolved_path) != 0) {
+ unlink(sock_file);
+ return;
}
+
+ resolved_path.resize(108); // sizeof(addr.sun_path) is 108
- bool success = true;
- char buffer[256];
- const int buffer_size = snprintf(buffer, sizeof(buffer), "%ld", (long)getpid());
- if(write(fd, buffer, buffer_size) == -1) {
- perror("failed to write quickmedia pid file");
- success = false;
+ if(resolved_path.size() < 4 || memcmp(resolved_path.data(), "/tmp", 4) != 0) {
+ unlink(sock_file);
+ return;
}
-
- close(fd);
- if(!success)
- unlink(pid_file);
- return success;
- }
-
- void remove_quickmedia_instance_lock(const char *pid_file_dir, const char *plugin_name) {
- char pid_file[PATH_MAX];
- snprintf(pid_file, sizeof(pid_file), "%s/quickmedia.%s.pid", pid_file_dir, plugin_name);
- unlink(pid_file);
+
+ unlink(sock_file);
+ unlink(resolved_path.c_str());
}
} \ No newline at end of file