From 247d83b1eaa64dd28900f90763dd02e71d5bd3f6 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 10 Dec 2022 01:18:35 +0100 Subject: Matrix: use unix domain socket for unique process file instead --- src/plugins/utils/UniqueProcess.cpp | 154 ++++++++++++++++++------------------ 1 file changed, 76 insertions(+), 78 deletions(-) (limited to 'src/plugins/utils') 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 -#include #include +#include +#include #include #include -#include +#include 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 -- cgit v1.2.3