1 /* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc. 4 * Copyright (C) 2009 Juan Cespedes 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of the 9 * License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 19 * 02110-1301 USA 20 */ 21 22 #include "config.h" 23 24 #include <sys/param.h> 25 #include <sys/wait.h> 26 #include <errno.h> 27 #include <limits.h> 28 #include <locale.h> 29 #include <signal.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 #include "backend.h" 36 #include "common.h" 37 #include "proc.h" 38 #include "prototype.h" 39 #include "read_config_file.h" 40 #include "summary.h" 41 42 char *command = NULL; 43 44 int exiting = 0; /* =1 if a SIGINT or SIGTERM has been received */ 45 46 static enum callback_status 47 stop_non_p_processes(struct process *proc, void *data) 48 { 49 int stop = 1; 50 51 struct opt_p_t *it; 52 for (it = opt_p; it != NULL; it = it->next) { 53 struct process *p_proc = pid2proc(it->pid); 54 if (p_proc == NULL) { 55 printf("stop_non_p_processes: %d terminated?\n", it->pid); 56 continue; 57 } 58 if (p_proc == proc || p_proc->leader == proc->leader) { 59 stop = 0; 60 break; 61 } 62 } 63 64 if (stop) { 65 debug(2, "Sending SIGSTOP to process %u", proc->pid); 66 kill(proc->pid, SIGSTOP); 67 } 68 69 return CBS_CONT; 70 } 71 72 static void 73 signal_alarm(int sig) { 74 signal(SIGALRM, SIG_DFL); 75 each_process(NULL, &stop_non_p_processes, NULL); 76 } 77 78 static void 79 signal_exit(int sig) 80 { 81 if (exiting != 0) 82 return; 83 84 exiting = 1 + !!os_ltrace_exiting_sighandler(); 85 86 signal(SIGINT, SIG_IGN); 87 signal(SIGTERM, SIG_IGN); 88 signal(SIGALRM, signal_alarm); 89 //alarm(1); 90 } 91 92 static void 93 normal_exit(void) 94 { 95 if (options.summary) 96 show_summary(); 97 if (options.output) { 98 fclose(options.output); 99 options.output = NULL; 100 } 101 } 102 103 void 104 ltrace_init(int argc, char **argv) 105 { 106 setlocale(LC_ALL, ""); 107 108 struct opt_p_t *opt_p_tmp; 109 110 atexit(normal_exit); 111 signal(SIGINT, signal_exit); /* Detach processes when interrupted */ 112 signal(SIGTERM, signal_exit); /* ... or killed */ 113 114 argv = process_options(argc, argv); 115 init_global_config(); 116 117 if (command) { 118 /* Check that the binary ABI is supported before 119 * calling execute_program. */ 120 { 121 struct ltelf lte; 122 if (ltelf_init(<e, command) == 0) 123 ltelf_destroy(<e); 124 else 125 exit(EXIT_FAILURE); 126 } 127 128 pid_t pid = execute_program(command, argv); 129 struct process *proc = open_program(command, pid); 130 if (proc == NULL) { 131 fprintf(stderr, "couldn't open program '%s': %s\n", 132 command, strerror(errno)); 133 exit(EXIT_FAILURE); 134 } 135 136 trace_set_options(proc); 137 continue_process(pid); 138 } 139 opt_p_tmp = opt_p; 140 while (opt_p_tmp) { 141 open_pid(opt_p_tmp->pid); 142 opt_p_tmp = opt_p_tmp->next; 143 } 144 } 145 146 static int num_ltrace_callbacks[EVENT_MAX]; 147 static callback_func * ltrace_callbacks[EVENT_MAX]; 148 149 void 150 ltrace_add_callback(callback_func func, Event_type type) { 151 ltrace_callbacks[type] = realloc(ltrace_callbacks[type], (num_ltrace_callbacks[type]+1)*sizeof(callback_func)); 152 ltrace_callbacks[type][num_ltrace_callbacks[type]++] = func; 153 } 154 155 static void 156 dispatch_callbacks(Event * ev) { 157 int i; 158 /* Ignoring case 1: signal into a dying tracer */ 159 if (ev->type==EVENT_SIGNAL && 160 exiting && ev->e_un.signum == SIGSTOP) { 161 return; 162 } 163 /* Ignoring case 2: process being born before a clone event */ 164 if (ev->proc && ev->proc->state == STATE_IGNORED) { 165 return; 166 } 167 for (i=0; i<num_ltrace_callbacks[ev->type]; i++) { 168 ltrace_callbacks[ev->type][i](ev); 169 } 170 } 171 172 void 173 ltrace_main(void) { 174 Event * ev; 175 while (1) { 176 ev = next_event(); 177 dispatch_callbacks(ev); 178 handle_event(ev); 179 } 180 } 181