summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Pereiaslov <perk11@perk11.info>2023-10-01 22:53:47 -0500
committerKonstantin Pereiaslov <perk11@perk11.info>2023-10-01 23:14:10 -0500
commita983cb2490eb2d794ed5f9b997620dda27527b1e (patch)
treee46ceb633a2c8d4aa40926039e760fb1e4ade685
parent77b26a4cdf54f71ffa26220df2f8671af100ed9f (diff)
First version of pausing/resuming recursively
-rw-r--r--main.c6
-rw-r--r--process_handling.c78
-rw-r--r--process_handling.h18
3 files changed, 97 insertions, 5 deletions
diff --git a/main.c b/main.c
index a51ed51..ef98711 100644
--- a/main.c
+++ b/main.c
@@ -58,7 +58,7 @@ int handle_interruption() {
"Since command was previously paused, we will try to resume it now to be able to handle the interruption before exiting\n"
);
}
- resume_command(pid);
+ resume_command_recursively(pid);
}
//Wait for the child process to complete
return wait_for_pid_to_exit_synchronously(pid);
@@ -93,7 +93,7 @@ long long pause_or_resume_command_depending_on_user_activity(
printf("Lack of user activity detected. ");
//intentionally no new line here, resume_command will print the rest of the message.
}
- resume_command(pid);
+ resume_command_recursively(pid);
command_paused = 0;
}
} else {
@@ -105,7 +105,7 @@ long long pause_or_resume_command_depending_on_user_activity(
if (verbose) {
fprintf(stderr, "Idle time: %lums.\n", user_idle_time_ms);
}
- pause_command(pid);
+ pause_command_recursively(pid);
if (debug) fprintf(stderr,"Command paused\n");
command_paused = 1;
command_was_paused_this_iteration = 1;
diff --git a/process_handling.c b/process_handling.c
index 9f1d414..a3ab85d 100644
--- a/process_handling.c
+++ b/process_handling.c
@@ -5,6 +5,7 @@
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
+#include <dirent.h>
#include "process_handling.h"
#include "output_settings.h"
@@ -41,6 +42,52 @@ pid_t run_shell_command(const char *shell_command_to_run) {
void handle_kill_error(char *signal_name, pid_t pid, int kill_errno) {
fprintf(stderr, "Failed to send %s signal to PID %i: %s\n", signal_name, pid, strerror(kill_errno));
}
+typedef struct ProcessNode {
+ int process_id;
+ struct ProcessNode* next_node;
+} ProcessNode;
+
+
+ProcessNode* get_child_processes_linked_list(int parent_process_id) {
+ DIR *proc_directory = opendir("/proc/");
+ if (proc_directory == NULL) {
+ fprintf_error("Could not open /proc directory");
+ exit(1);
+ }
+
+ ProcessNode *head_node = NULL, **tail_node = &head_node;
+ struct dirent *directory_entry;
+ char stat_file_path[64];
+ int process_id, found_parent_process_id;
+ FILE *stat_file;
+
+ while ((directory_entry = readdir(proc_directory)) != NULL) {
+ if (sscanf(directory_entry->d_name, "%d", &process_id) != 1) continue;
+
+ snprintf(stat_file_path, sizeof(stat_file_path), "/proc/%d/stat", process_id);
+ stat_file = fopen(stat_file_path, "r");
+ if (stat_file == NULL) continue;
+
+ fscanf(stat_file, "%*d %*s %*c %d", &found_parent_process_id);
+ fclose(stat_file);
+
+ if (found_parent_process_id != parent_process_id) continue;
+
+ ProcessNode *new_node = (ProcessNode *)malloc(sizeof(ProcessNode));
+ if (new_node == NULL) {
+ perror("Memory allocation failed");
+ exit(1);
+ }
+
+ new_node->process_id = process_id;
+ new_node->next_node = NULL;
+ *tail_node = new_node;
+ tail_node = &(new_node->next_node);
+ }
+
+ closedir(proc_directory);
+ return head_node;
+}
void send_signal_to_pid(pid_t pid, int signal, char *signal_name) {
if (debug) {
@@ -57,7 +104,7 @@ void send_signal_to_pid(pid_t pid, int signal, char *signal_name) {
void pause_command(pid_t pid) {
if (!quiet) {
- printf("User activity is detected, pausing PID %i\n", pid);
+ printf("Pausing PID %i\n", pid);
}
switch (pause_method) {
case PAUSE_METHOD_SIGTSTP:
@@ -72,6 +119,21 @@ void pause_command(pid_t pid) {
}
}
+void pause_command_recursively(pid_t pid)
+{
+ pause_command(pid);
+ ProcessNode* child_process_ids = get_child_processes_linked_list(pid);
+ ProcessNode* current_node = child_process_ids;
+ ProcessNode* previous_node;
+
+ while (current_node) {
+ pause_command(current_node->process_id);
+ previous_node = current_node;
+ current_node = current_node->next_node;
+ free(previous_node);
+ }
+}
+
void resume_command(pid_t pid) {
if (!quiet) {
printf("Resuming PID %i\n", pid);
@@ -79,6 +141,20 @@ void resume_command(pid_t pid) {
send_signal_to_pid(pid, SIGCONT, "SIGCONT");
}
+void resume_command_recursively(pid_t pid)
+{
+ resume_command(pid);
+ ProcessNode* child_process_ids = get_child_processes_linked_list(pid);
+ ProcessNode* current_node = child_process_ids;
+ ProcessNode* previous_node;
+
+ while (current_node) {
+ resume_command(current_node->process_id);
+ previous_node = current_node;
+ current_node = current_node->next_node;
+ free(previous_node);
+ }
+}
int wait_for_pid_to_exit_synchronously(int pid) {
int status;
diff --git a/process_handling.h b/process_handling.h
index 2153797..c3cdb13 100644
--- a/process_handling.h
+++ b/process_handling.h
@@ -9,13 +9,21 @@
*/
void send_signal_to_pid(pid_t pid, int signal, char *signal_name);
/**
- * Pauses a specified process by sending the SIGTSTP signal.
+ * Pauses a specified process using pause method specified in pause_method variable
*
* @param pid The process ID of the target process.
*/
void pause_command(pid_t pid);
/**
+ * Pauses a specified process and all child processes
+ *
+ * @param pid The process ID of the target process.
+ */
+void pause_command_recursively(pid_t pid);
+
+
+/**
* Resumes a specified process by sending the SIGCONT signal.
*
* @param pid The process ID of the target process.
@@ -23,6 +31,14 @@ void pause_command(pid_t pid);
void resume_command(pid_t pid);
/**
+ * Resumes a specified process and all child processes by sending SIGCONT signal to each process.
+ *
+ * @param pid The process ID of the target process.
+ */
+void resume_command_recursively(pid_t pid);
+
+
+/**
* Executes a shell command in a new process and returns the process ID of the child process.
* On failure will exit.
*