Skip to content

Commit

Permalink
Perform cleanup actions on exit with signals
Browse files Browse the repository at this point in the history
  • Loading branch information
thevindu-w committed Aug 14, 2024
1 parent edd1c5b commit 358776a
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 31 deletions.
76 changes: 61 additions & 15 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ static inline void _parse_args(int argc, char **argv, int *stop_p, int *daemoniz
switch (opt) {
case 'h': { // help
print_usage(argv[0]);
exit_wrapper(EXIT_SUCCESS);
exit(EXIT_SUCCESS);
}
case 's': { // stop
*stop_p = 1;
Expand All @@ -115,7 +115,7 @@ static inline void _parse_args(int argc, char **argv, int *stop_p, int *daemoniz
}
default: {
print_usage(argv[0]);
exit_wrapper(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
}
}
Expand All @@ -126,12 +126,12 @@ static inline void _parse_args(int argc, char **argv, int *stop_p, int *daemoniz
*/
static inline void _set_error_log_file(const char *path) {
char *working_dir = getcwd_wrapper(2050);
if (!working_dir) exit_wrapper(EXIT_FAILURE);
if (!working_dir) exit(EXIT_FAILURE);
working_dir[2049] = 0;
size_t working_dir_len = strnlen(working_dir, 2048);
if (working_dir_len == 0 || working_dir_len >= 2048) {
free(working_dir);
exit_wrapper(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
size_t buf_sz = working_dir_len + strlen(path) + 1; // +1 for terminating \0
if (working_dir[working_dir_len - 1] != PATH_SEP) {
Expand All @@ -140,7 +140,7 @@ static inline void _set_error_log_file(const char *path) {
error_log_file = malloc(buf_sz);
if (!error_log_file) {
free(working_dir);
exit_wrapper(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
if (working_dir[working_dir_len - 1] == PATH_SEP) {
snprintf_check(error_log_file, buf_sz, "%s%s", working_dir, ERROR_LOG_FILE);
Expand Down Expand Up @@ -249,6 +249,7 @@ static void kill_other_processes(const char *prog_name) {
#endif
return;
}
int killed = 0;
while ((dir_ptr = readdir(dir)) != NULL) {
if ((strcmp(dir_ptr->d_name, ".") == 0) || (strcmp(dir_ptr->d_name, "..") == 0)) continue;
if (DT_DIR != dir_ptr->d_type) continue;
Expand Down Expand Up @@ -285,11 +286,16 @@ static void kill_other_processes(const char *prog_name) {
fprintf(stderr, "killed %s\n", dir_ptr->d_name);
#endif
kill(pid, SIGTERM);
killed = 1;
}
}
fclose(fp);
}
(void)closedir(dir);
if (killed) {
struct timespec interval = {.tv_sec = 0, .tv_nsec = 5000000};
nanosleep(&interval, NULL);
}
return;
}

Expand All @@ -308,19 +314,34 @@ static volatile char running = 1;
* It is not guaranteed to kill all processes with the given name.
*/
static void kill_other_processes(const char *prog_name) {
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
}
DWORD this_pid = GetCurrentProcessId();
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (Process32First(snapshot, &entry) == TRUE) {
while (Process32Next(snapshot, &entry) == TRUE) {
if ((stricmp(entry.szExeFile, prog_name) == 0) && (entry.th32ProcessID != this_pid)) {
FreeConsole();
AttachConsole(entry.th32ProcessID);
SetConsoleCtrlHandler(NULL, TRUE);
GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
FreeConsole();
Sleep(10);
SetConsoleCtrlHandler(NULL, FALSE);
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, entry.th32ProcessID);
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
if (hProcess != INVALID_HANDLE_VALUE) {
TerminateProcess(hProcess, 0);
CloseHandle(hProcess);
}
}
}
}
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
}
CloseHandle(snapshot);
}

Expand Down Expand Up @@ -402,6 +423,7 @@ static inline void remove_tray_icon(void) {

static LRESULT CALLBACK WindowProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_QUERYENDSESSION:
case WM_COMMAND: {
remove_tray_icon();
running = 0;
Expand Down Expand Up @@ -510,6 +532,7 @@ static void kill_other_processes(const char *prog_name) {

pid_t this_pid = getpid();
char pname[32];
int killed = 0;
for (size_t i = 0; i < count; i++) {
pid_t pid = procs[i].kp_proc.p_pid;
pname[0] = 0;
Expand All @@ -520,10 +543,15 @@ static void kill_other_processes(const char *prog_name) {
fprintf(stderr, "killed %i\n", pid);
#endif
kill(pid, SIGTERM);
killed = 1;
}
}
}
free(procs);
if (killed) {
struct timespec interval = {.tv_sec = 0, .tv_nsec = 5000000};
nanosleep(&interval, NULL);
}
}

#endif
Expand All @@ -544,6 +572,11 @@ static char *get_user_home(void) {
return NULL;
}

__attribute__((noreturn)) static void exit_on_signal_handler(int sig) {
(void)sig;
exit(0);
}

#endif

static char *get_conf_file(void) {
Expand Down Expand Up @@ -586,6 +619,20 @@ int main(int argc, char **argv) {
prog_name++; // don't want the '/' before the program name
}

atexit(cleanup);

#if defined(__linux__) || defined(__APPLE__)
signal(SIGCHLD, SIG_IGN);
signal(SIGINT, &exit_on_signal_handler);
signal(SIGTERM, &exit_on_signal_handler);
signal(SIGSEGV, &exit_on_signal_handler);
signal(SIGABRT, &exit_on_signal_handler);
signal(SIGQUIT, &exit_on_signal_handler);
signal(SIGSYS, &exit_on_signal_handler);
signal(SIGHUP, &exit_on_signal_handler);
signal(SIGBUS, &exit_on_signal_handler);
#endif

_set_error_log_file(ERROR_LOG_FILE);

#ifdef _WIN32
Expand All @@ -596,7 +643,7 @@ int main(int argc, char **argv) {

char *conf_path = get_conf_file();
if (!conf_path) {
exit_wrapper(EXIT_FAILURE);
exit(EXIT_FAILURE);
}
parse_conf(&configuration, conf_path);
free(conf_path);
Expand All @@ -617,7 +664,7 @@ int main(int argc, char **argv) {
const char *msg = stop ? "Server Stopped" : "Server Restarting...";
puts(msg);
if (stop) {
exit_wrapper(EXIT_SUCCESS);
exit(EXIT_SUCCESS);
}
}

Expand Down Expand Up @@ -648,7 +695,7 @@ int main(int argc, char **argv) {
p_clip = fork();
if (p_clip == 0) {
int status = clip_share(INSECURE);
exit_wrapper(status);
exit(status);
}
}
if (configuration.secure_mode_enabled) {
Expand All @@ -657,7 +704,7 @@ int main(int argc, char **argv) {
p_clip_ssl = fork();
if (p_clip_ssl == 0) {
int status = clip_share(SECURE);
exit_wrapper(status);
exit(status);
}
}
#ifdef WEB_ENABLED
Expand All @@ -667,7 +714,7 @@ int main(int argc, char **argv) {
p_web = fork();
if (p_web == 0) {
int status = web_server();
exit_wrapper(status);
exit(status);
}
}
#endif
Expand All @@ -677,7 +724,7 @@ int main(int argc, char **argv) {
pid_t p_scan = fork();
if (p_scan == 0) {
udp_server();
exit_wrapper(EXIT_SUCCESS);
exit(EXIT_SUCCESS);
}

if (!daemonize) {
Expand Down Expand Up @@ -762,10 +809,9 @@ int main(int argc, char **argv) {
#ifdef WEB_ENABLED
if (webThread != NULL) WaitForSingleObject(webThread, INFINITE);
#endif
WSACleanup();

remove_tray_icon();
CloseHandle(instance);
#endif
exit_wrapper(EXIT_SUCCESS);
return 0;
}
5 changes: 1 addition & 4 deletions servers/clip_share.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <utils/net_utils.h>
#include <utils/utils.h>
#if defined(__linux__) || defined(__APPLE__)
#include <signal.h>
#include <sys/socket.h>
#include <unistd.h>
#elif defined(_WIN32)
Expand Down Expand Up @@ -75,9 +74,7 @@ int clip_share(const int is_secure) {
error("Can\'t listen");
return EXIT_FAILURE;
}
#if defined(__linux__) || defined(__APPLE__)
signal(SIGCHLD, SIG_IGN);
#endif

while (1) {
socket_t connect_sock;
get_connection(&connect_sock, listener, configuration.allowed_clients);
Expand Down
3 changes: 0 additions & 3 deletions servers/clip_share_web.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,6 @@ int web_server(void) {
#endif
return EXIT_FAILURE;
}
#ifdef __linux__
signal(SIGCHLD, SIG_IGN);
#endif

listener_t listener;
open_listener_socket(&listener, SSL_SOCK, configuration.priv_key, configuration.server_cert, configuration.ca_cert);
Expand Down
5 changes: 5 additions & 0 deletions utils/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,17 +392,22 @@ void clear_config(config *cfg) {
size_t len = strnlen(cfg->priv_key, 65536);
memset(cfg->priv_key, 0, len);
free(cfg->priv_key);
cfg->priv_key = NULL;
}
if (cfg->server_cert) {
free(cfg->server_cert);
cfg->server_cert = NULL;
}
if (cfg->ca_cert) {
free(cfg->ca_cert);
cfg->ca_cert = NULL;
}
if (cfg->working_dir) {
free(cfg->working_dir);
cfg->working_dir = NULL;
}
if (cfg->allowed_clients) {
free_list(cfg->allowed_clients);
cfg->allowed_clients = NULL;
}
}
29 changes: 22 additions & 7 deletions utils/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ void error(const char *msg) {

void error_exit(const char *msg) {
error(msg);
exit_wrapper(EXIT_FAILURE);
exit(EXIT_FAILURE);
}

#ifdef __linux__
Expand Down Expand Up @@ -109,15 +109,30 @@ static void freeAtomPtr(AtomPtr atomPtr) {
}
#endif

void exit_wrapper(int code) {
if (error_log_file) free(error_log_file);
if (cwd) free(cwd);
void cleanup(void) {
#ifdef DEBUG_MODE
#ifdef _WIN32
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
freopen("CONOUT$", "w", stdout);
}
#endif
puts("Cleaning up resources before exit");
#endif
if (error_log_file) {
free(error_log_file);
error_log_file = NULL;
}
if (cwd) {
free(cwd);
cwd = NULL;
}
clear_config(&configuration);
#ifdef __linux__
freeAtomPtr(_XA_CLIPBOARD);
freeAtomPtr(_XA_UTF8_STRING);
if (_XA_CLIPBOARD) freeAtomPtr(_XA_CLIPBOARD);
if (_XA_UTF8_STRING) freeAtomPtr(_XA_UTF8_STRING);
#elif defined(_WIN32)
WSACleanup();
#endif
exit(code);
}

int file_exists(const char *file_name) {
Expand Down
4 changes: 2 additions & 2 deletions utils/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ extern void error(const char *msg);
extern void error_exit(const char *msg) __attribute__((noreturn));

/*
* Exit after clearing config and other memory allocations
* Free up heap memory allocated to global variables
*/
void exit_wrapper(int code) __attribute__((noreturn));
extern void cleanup(void);

/*
* Get copied text from clipboard.
Expand Down

0 comments on commit 358776a

Please sign in to comment.