in src/guacd/proc.c [325:417]
static void guacd_exec_proc(guacd_proc* proc, const char* protocol) {
int result = 1;
/* Set process group ID to match PID */
if (setpgid(0, 0)) {
guacd_log(GUAC_LOG_ERROR, "Cannot set PGID for connection process: %s",
strerror(errno));
goto cleanup_process;
}
/* Init client for selected protocol */
guac_client* client = proc->client;
if (guac_client_load_plugin(client, protocol)) {
/* Log error */
if (guac_error == GUAC_STATUS_NOT_FOUND)
guacd_log(GUAC_LOG_WARNING,
"Support for protocol \"%s\" is not installed", protocol);
else
guacd_log_guac_error(GUAC_LOG_ERROR,
"Unable to load client plugin");
goto cleanup_client;
}
/* The first file descriptor is the owner */
int owner = 1;
/* Enable keep alive on the broadcast socket */
guac_socket_require_keep_alive(client->socket);
guacd_proc_self = proc;
/* Clean up and exit if SIGINT or SIGTERM signals are caught */
struct sigaction signal_stop_action = { .sa_handler = signal_stop_handler };
sigaction(SIGINT, &signal_stop_action, NULL);
sigaction(SIGTERM, &signal_stop_action, NULL);
/* Add each received file descriptor as a new user */
int received_fd;
while ((received_fd = guacd_recv_fd(proc->fd_socket)) != -1) {
guacd_proc_add_user(proc, received_fd, owner);
/* Future file descriptors are not owners */
owner = 0;
}
cleanup_client:
/* Request client to stop/disconnect */
guac_client_stop(client);
/* Attempt to free client cleanly */
guacd_log(GUAC_LOG_DEBUG, "Requesting termination of client...");
result = guacd_timed_client_free(client, GUACD_CLIENT_FREE_TIMEOUT);
/* If client was unable to be freed, warn and forcibly kill */
if (result) {
guacd_log(GUAC_LOG_WARNING, "Client did not terminate in a timely "
"manner. Forcibly terminating client and any child "
"processes.");
guacd_kill_current_proc_group();
}
else
guacd_log(GUAC_LOG_DEBUG, "Client terminated successfully.");
/* Verify whether children were all properly reaped */
pid_t child_pid;
while ((child_pid = waitpid(0, NULL, WNOHANG)) > 0) {
guacd_log(GUAC_LOG_DEBUG, "Automatically reaped unreaped "
"(zombie) child process with PID %i.", child_pid);
}
/* If running children remain, warn and forcibly kill */
if (child_pid == 0) {
guacd_log(GUAC_LOG_WARNING, "Client reported successful termination, "
"but child processes remain. Forcibly terminating client and "
"child processes.");
guacd_kill_current_proc_group();
}
cleanup_process:
/* Free up all internal resources outside the client */
close(proc->fd_socket);
guac_mem_free(proc);
exit(result);
}