libltrace.c revision 0ba3c5eee259b77e3883e40c4d0cd2fab5b03ff3
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 "common.h" 36#include "proc.h" 37#include "read_config_file.h" 38#include "backend.h" 39#include "prototype.h" 40 41char *command = NULL; 42 43int exiting = 0; /* =1 if a SIGINT or SIGTERM has been received */ 44 45static enum callback_status 46stop_non_p_processes(struct process *proc, void *data) 47{ 48 int stop = 1; 49 50 struct opt_p_t *it; 51 for (it = opt_p; it != NULL; it = it->next) { 52 struct process *p_proc = pid2proc(it->pid); 53 if (p_proc == NULL) { 54 printf("stop_non_p_processes: %d terminated?\n", it->pid); 55 continue; 56 } 57 if (p_proc == proc || p_proc->leader == proc->leader) { 58 stop = 0; 59 break; 60 } 61 } 62 63 if (stop) { 64 debug(2, "Sending SIGSTOP to process %u", proc->pid); 65 kill(proc->pid, SIGSTOP); 66 } 67 68 return CBS_CONT; 69} 70 71static void 72signal_alarm(int sig) { 73 signal(SIGALRM, SIG_DFL); 74 each_process(NULL, &stop_non_p_processes, NULL); 75} 76 77static void 78signal_exit(int sig) 79{ 80 if (exiting != 0) 81 return; 82 83 exiting = 1 + !!os_ltrace_exiting_sighandler(); 84 85 signal(SIGINT, SIG_IGN); 86 signal(SIGTERM, SIG_IGN); 87 signal(SIGALRM, signal_alarm); 88 //alarm(1); 89} 90 91static void 92normal_exit(void) 93{ 94 if (options.summary) 95 show_summary(); 96 if (options.output) { 97 fclose(options.output); 98 options.output = NULL; 99 } 100} 101 102void 103ltrace_init(int argc, char **argv) 104{ 105 setlocale(LC_ALL, ""); 106 107 struct opt_p_t *opt_p_tmp; 108 109 atexit(normal_exit); 110 signal(SIGINT, signal_exit); /* Detach processes when interrupted */ 111 signal(SIGTERM, signal_exit); /* ... or killed */ 112 113 argv = process_options(argc, argv); 114 init_global_config(); 115 116 if (command) { 117 /* Check that the binary ABI is supported before 118 * calling execute_program. */ 119 { 120 struct ltelf lte; 121 if (ltelf_init(<e, command) == 0) 122 ltelf_destroy(<e); 123 else 124 exit(EXIT_FAILURE); 125 } 126 127 pid_t pid = execute_program(command, argv); 128 struct process *proc = open_program(command, pid); 129 if (proc == NULL) { 130 fprintf(stderr, "couldn't open program '%s': %s\n", 131 command, strerror(errno)); 132 exit(EXIT_FAILURE); 133 } 134 135 trace_set_options(proc); 136 continue_process(pid); 137 } 138 opt_p_tmp = opt_p; 139 while (opt_p_tmp) { 140 open_pid(opt_p_tmp->pid); 141 opt_p_tmp = opt_p_tmp->next; 142 } 143} 144 145static int num_ltrace_callbacks[EVENT_MAX]; 146static callback_func * ltrace_callbacks[EVENT_MAX]; 147 148void 149ltrace_add_callback(callback_func func, Event_type type) { 150 ltrace_callbacks[type] = realloc(ltrace_callbacks[type], (num_ltrace_callbacks[type]+1)*sizeof(callback_func)); 151 ltrace_callbacks[type][num_ltrace_callbacks[type]++] = func; 152} 153 154static void 155dispatch_callbacks(Event * ev) { 156 int i; 157 /* Ignoring case 1: signal into a dying tracer */ 158 if (ev->type==EVENT_SIGNAL && 159 exiting && ev->e_un.signum == SIGSTOP) { 160 return; 161 } 162 /* Ignoring case 2: process being born before a clone event */ 163 if (ev->proc && ev->proc->state == STATE_IGNORED) { 164 return; 165 } 166 for (i=0; i<num_ltrace_callbacks[ev->type]; i++) { 167 ltrace_callbacks[ev->type][i](ev); 168 } 169} 170 171void 172ltrace_main(void) { 173 Event * ev; 174 while (1) { 175 ev = next_event(); 176 dispatch_callbacks(ev); 177 handle_event(ev); 178 } 179} 180