1 | /* |
---|
2 | orxonox - the future of 3D-vertical-scrollers |
---|
3 | |
---|
4 | Copyright (C) 2004 orx |
---|
5 | |
---|
6 | This program is free software; you can redistribute it and/or modify |
---|
7 | it under the terms of the GNU General Public License as published by |
---|
8 | the Free Software Foundation; either version 2, or (at your option) |
---|
9 | any later version. |
---|
10 | |
---|
11 | ### File Specific: |
---|
12 | main-programmer: Christoph Renner |
---|
13 | co-programmer: ... |
---|
14 | */ |
---|
15 | |
---|
16 | #include "signal_handler.h" |
---|
17 | #include <assert.h> |
---|
18 | |
---|
19 | SignalHandler * SignalHandler::singletonRef = NULL; |
---|
20 | |
---|
21 | #ifndef __WIN32__ |
---|
22 | |
---|
23 | SignalHandler::SignalHandler() |
---|
24 | { |
---|
25 | } |
---|
26 | |
---|
27 | void SignalHandler::doCatch( std::string appName, GdbRunType type ) |
---|
28 | { |
---|
29 | this->type = type; |
---|
30 | this->appName = appName; |
---|
31 | |
---|
32 | catchSignal( SIGSEGV ); |
---|
33 | catchSignal( SIGABRT ); |
---|
34 | } |
---|
35 | |
---|
36 | void SignalHandler::dontCatch() |
---|
37 | { |
---|
38 | for ( SignalRecList::iterator it = sigRecList.begin(); it != sigRecList.end(); it++ ) |
---|
39 | { |
---|
40 | signal( it->signal, it->handler ); |
---|
41 | } |
---|
42 | |
---|
43 | sigRecList.clear(); |
---|
44 | } |
---|
45 | |
---|
46 | void SignalHandler::catchSignal( int sig ) |
---|
47 | { |
---|
48 | sighandler_t handler = signal( sig, SignalHandler::sigHandler ); |
---|
49 | |
---|
50 | assert( handler != SIG_ERR ); |
---|
51 | |
---|
52 | SignalRec rec; |
---|
53 | rec.signal = sig; |
---|
54 | rec.handler = handler; |
---|
55 | |
---|
56 | sigRecList.push_front( rec ); |
---|
57 | } |
---|
58 | |
---|
59 | void SignalHandler::sigHandler( int sig ) |
---|
60 | { |
---|
61 | for ( SignalCallbackList::iterator it = SignalHandler::getInstance()->callbackList.begin(); it != SignalHandler::getInstance()->callbackList.end(); it++ ) |
---|
62 | { |
---|
63 | (*(it->cb))( it->someData ); |
---|
64 | } |
---|
65 | |
---|
66 | std::string sigName = "UNKNOWN"; |
---|
67 | |
---|
68 | switch ( sig ) |
---|
69 | { |
---|
70 | case SIGSEGV: |
---|
71 | sigName = "SIGSEGV"; |
---|
72 | break; |
---|
73 | case SIGABRT: |
---|
74 | sigName = "SIGABRT"; |
---|
75 | break; |
---|
76 | } |
---|
77 | |
---|
78 | printf( "recieved signal %s\ntry to write backtrace to file orxonox.backtrace\n", sigName.c_str() ); |
---|
79 | |
---|
80 | int fd[2]; |
---|
81 | |
---|
82 | assert( pipe(fd) != -1 ); |
---|
83 | |
---|
84 | int pid = fork(); |
---|
85 | |
---|
86 | assert( pid != -1 ); |
---|
87 | |
---|
88 | |
---|
89 | if ( pid == 0 ) |
---|
90 | { |
---|
91 | getInstance()->dontCatch(); |
---|
92 | |
---|
93 | sleep(2); |
---|
94 | |
---|
95 | return; |
---|
96 | } |
---|
97 | else |
---|
98 | { |
---|
99 | getInstance()->dontCatch(); |
---|
100 | if ( getInstance()->type == GDB_RUN_WRITE_TO_FILE && fork() == 0 ) |
---|
101 | { |
---|
102 | sleep(1); |
---|
103 | write( fd[1], "c\nbt\nq\n", 7 ); |
---|
104 | |
---|
105 | exit(0); |
---|
106 | } |
---|
107 | |
---|
108 | char command[256]; |
---|
109 | if ( getInstance()->type == GDB_RUN_WRITE_TO_FILE ) |
---|
110 | { |
---|
111 | dup2( fd[0], STDIN_FILENO ); |
---|
112 | snprintf( command, 255, "gdb -p %d %s 1>>" GDB_BT_FILE " 2>&1", pid, getInstance()->appName.c_str() ); |
---|
113 | } |
---|
114 | else |
---|
115 | snprintf( command, 255, "gdb -p %d %s", pid, getInstance()->appName.c_str() ); |
---|
116 | execlp( "sh", "sh", "-c", command, (void*)NULL); |
---|
117 | } |
---|
118 | } |
---|
119 | |
---|
120 | void SignalHandler::registerCallback( SignalCallback cb, void * someData ) |
---|
121 | { |
---|
122 | SignalCallbackRec rec; |
---|
123 | rec.cb = cb; |
---|
124 | rec.someData = someData; |
---|
125 | |
---|
126 | callbackList.push_back(rec); |
---|
127 | } |
---|
128 | |
---|
129 | #endif /* __WIN32__ */ |
---|