From 137a18719ce8006697bb104c9ea94115557b7966 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 17 Jul 2020 11:04:28 +0200 Subject: Fix automedia.pid always being overwritten --- src/main.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 16 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index e5c5321..c9a9bb3 100644 --- a/src/main.c +++ b/src/main.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -273,6 +274,12 @@ int is_program_running() { /* plugin is NULL for rss */ typedef int (*IterateTrackedItemCallback)(char *title, char *link, char *plugin, char *config_dir, struct json_object_s *json_data, void *userdata); static void iterate_tracked_items(char *config_dir, IterateTrackedItemCallback iterate_callback, void *userdata) { + /* + TODO: Only iterate updated items. To make that work, sync_rss and sync_html need to be updated to update + the json_object with new downloaded items (and not only temporary downloaded items) and then also only + clean them up! + */ + char tracked_dir[PATH_MAX]; strcpy(tracked_dir, config_dir); strcat(tracked_dir, "/tracked"); @@ -458,8 +465,9 @@ static void sync_rss_html(char *rss_config_dir, char *html_config_dir, char *pro free(unfinished_torrents.items); } -static int cmdline_contains_str(const char *cmdline, const char *str) { - for(;;) { +static int cmdline_contains_str(const char *cmdline, int cmdline_len, const char *str) { + const char *start = cmdline; + while(cmdline - start < cmdline_len) { int arg_len = strlen(cmdline); if(arg_len == 0) return -1; @@ -467,8 +475,35 @@ static int cmdline_contains_str(const char *cmdline, const char *str) { if(strstr(cmdline, str)) return 0; - cmdline += arg_len; + cmdline += arg_len + 1; + } + return -1; +} + +/* We can't use file_get_content because reading the size of /proc//cmdline fails (returns 0) because its not a regular file */ +static int proc_read_cmdline(const char *pid_str, char *cmdline_data, int cmdline_data_size, int *cmdline_data_size_output) { + assert(cmdline_data_size > 0); + + char cmdline_file_path[128]; + sprintf(cmdline_file_path, "/proc/%s/cmdline", pid_str); + + int cmdline_fd = open(cmdline_file_path, O_RDONLY); + if(cmdline_fd == -1) { + fprintf(stderr, "Process %s doesn't exist\n", pid_str); + return -1; + } + + ssize_t bytes_read = read(cmdline_fd, cmdline_data, cmdline_data_size - 1); + if(bytes_read == -1) { + fprintf(stderr, "Failed to read %s\n", cmdline_file_path); + close(cmdline_fd); + return -1; } + + cmdline_data[bytes_read] = '\0'; + *cmdline_data_size_output = bytes_read; + close(cmdline_fd); + return 0; } static void command_sync(int argc, char **argv, char *rss_config_dir, char *html_config_dir, char *program_dir) { @@ -483,6 +518,7 @@ static void command_sync(int argc, char **argv, char *rss_config_dir, char *html exit(1); } + /* Create a pid file because we only want to allow one instance of automedia to run at once */ int pid_file = open(automedia_pid_path, O_CREAT | O_EXCL | O_SYNC | O_RDWR, 0666); if(pid_file == -1 && errno == EEXIST) { char *running_automedia_pid; @@ -492,23 +528,18 @@ static void command_sync(int argc, char **argv, char *rss_config_dir, char *html We have to check the cmdline because another process could theoretically receive the pid that an old automedia process had */ - char cmdline_file_path[128]; - sprintf(cmdline_file_path, "/proc/%s/cmdline", running_automedia_pid); - free(running_automedia_pid); - - char *cmdline; - long cmdline_size; - if(file_get_content(cmdline_file_path, &cmdline, &cmdline_size) == 0 - && cmdline_contains_str(cmdline, "automedia") == 0 - && cmdline_contains_str(cmdline, "sync") == 0) { - fprintf(stderr, "Automedia is already running with sync"); - free(cmdline); + char cmdline[1024]; + int cmdline_size; + if(proc_read_cmdline(running_automedia_pid, cmdline, sizeof(cmdline), &cmdline_size) == 0 + && cmdline_contains_str(cmdline, cmdline_size, "automedia") == 0 + && cmdline_contains_str(cmdline, cmdline_size, "sync") == 0) { + fprintf(stderr, "Automedia is already running with sync\n"); + free(running_automedia_pid); exit(0); } - free(cmdline); + free(running_automedia_pid); } else { fprintf(stderr, "Failed to get content of %s\n", automedia_pid_path); - free(running_automedia_pid); exit(1); } -- cgit v1.2.3