aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/utils/UniqueProcess.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/utils/UniqueProcess.cpp')
-rw-r--r--src/plugins/utils/UniqueProcess.cpp111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/plugins/utils/UniqueProcess.cpp b/src/plugins/utils/UniqueProcess.cpp
new file mode 100644
index 0000000..d2025f5
--- /dev/null
+++ b/src/plugins/utils/UniqueProcess.cpp
@@ -0,0 +1,111 @@
+#include "../../../plugins/utils/UniqueProcess.hpp"
+#include "../../../include/Storage.hpp"
+#include <stdio.h>
+#include <limits.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+namespace QuickMedia {
+ 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);
+
+ std::string resolved_path;
+ if(file_get_content(sock_file, resolved_path) != 0)
+ return false;
+
+ resolved_path.resize(108); // sizeof(addr.sun_path) is 108
+
+ 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;
+ }
+
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
+
+ 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 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);
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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);
+
+ 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
+
+ if(resolved_path.size() < 4 || memcmp(resolved_path.data(), "/tmp", 4) != 0) {
+ unlink(sock_file);
+ return;
+ }
+
+ unlink(sock_file);
+ unlink(resolved_path.c_str());
+ }
+} \ No newline at end of file