doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
posix_signal.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 #include "../../idlib/precompiled.h"
29 #include "posix_public.h"
30 
31 #include <string.h>
32 #include <errno.h>
33 
34 const int siglist[] = {
35  SIGHUP,
36  SIGQUIT,
37  SIGILL,
38  SIGTRAP,
39  SIGIOT,
40  SIGBUS,
41  SIGFPE,
42  SIGSEGV,
43  SIGPIPE,
44  SIGABRT,
45  // SIGTTIN,
46  // SIGTTOU,
47  -1
48  };
49 
50 const char *signames[] = {
51  "SIGHUP",
52  "SIGQUIT",
53  "SIGILL",
54  "SIGTRAP",
55  "SIGIOT",
56  "SIGBUS",
57  "SIGFPE",
58  "SIGSEGV",
59  "SIGPIPE",
60  "SIGABRT",
61  // "SIGTTIN",
62  // "SIGTTOUT"
63 };
64 
65 static char fatalError[ 1024 ];
66 
67 /*
68 ================
69 Posix_ClearSigs
70 ================
71 */
72 void Posix_ClearSigs( ) {
73  struct sigaction action;
74  int i;
75 
76  /* Set up the structure */
77  action.sa_handler = SIG_DFL;
78  sigemptyset( &action.sa_mask );
79  action.sa_flags = 0;
80 
81  i = 0;
82  while ( siglist[ i ] != -1 ) {
83  if ( sigaction( siglist[ i ], &action, NULL ) != 0 ) {
84  Sys_Printf( "Failed to reset %s handler: %s\n", signames[ i ], strerror( errno ) );
85  }
86  i++;
87  }
88 }
89 
90 /*
91 ================
92 sig_handler
93 ================
94 */
95 static void sig_handler( int signum, siginfo_t *info, void *context ) {
96  static bool double_fault = false;
97 
98  if ( double_fault ) {
99  Sys_Printf( "double fault %s, bailing out\n", strsignal( signum ) );
100  Posix_Exit( signum );
101  }
102 
103  double_fault = true;
104 
105  // NOTE: see sigaction man page, could verbose the whole siginfo_t and print human readable si_code
106  Sys_Printf( "signal caught: %s\nsi_code %d\n", strsignal( signum ), info->si_code );
107 
108 #ifndef ID_BT_STUB
109  Sys_Printf( "callstack:\n%s", Sys_GetCallStackCurStr( 30 ) );
110 #endif
111 
112  if ( fatalError[ 0 ] ) {
113  Sys_Printf( "Was in fatal error shutdown: %s\n", fatalError );
114  }
115 
116  Sys_Printf( "Trying to exit gracefully..\n" );
117 
118  Posix_SetExit( signum );
119 
120  common->Quit();
121 }
122 
123 /*
124 ================
125 Posix_InitSigs
126 ================
127 */
128 void Posix_InitSigs( ) {
129  struct sigaction action;
130  int i;
131 
132  fatalError[0] = '\0';
133 
134  /* Set up the structure */
135  action.sa_sigaction = sig_handler;
136  sigemptyset( &action.sa_mask );
137  action.sa_flags = SA_SIGINFO | SA_NODEFER;
138 
139  i = 0;
140  while ( siglist[ i ] != -1 ) {
141  if ( siglist[ i ] == SIGFPE ) {
142  action.sa_sigaction = Sys_FPE_handler;
143  if ( sigaction( siglist[ i ], &action, NULL ) != 0 ) {
144  Sys_Printf( "Failed to set SIGFPE handler: %s\n", strerror( errno ) );
145  }
146  action.sa_sigaction = sig_handler;
147  } else if ( sigaction( siglist[ i ], &action, NULL ) != 0 ) {
148  Sys_Printf( "Failed to set %s handler: %s\n", signames[ i ], strerror( errno ) );
149  }
150  i++;
151  }
152 
153  // if the process is backgrounded (running non interactively)
154  // then SIGTTIN or SIGTOU could be emitted, if not caught, turns into a SIGSTP
155  signal( SIGTTIN, SIG_IGN );
156  signal( SIGTTOU, SIG_IGN );
157 }
158 
159 /*
160 ==================
161 Sys_SetFatalError
162 ==================
163 */
164 void Sys_SetFatalError( const char *error ) {
165  strncpy( fatalError, error, sizeof( fatalError ) );
166 }
void Sys_Printf(const char *msg,...)
const char * signames[]
int i
Definition: process.py:33
void Sys_FPE_handler(int signum, siginfo_t *info, void *context)
Definition: main.cpp:235
void Posix_Exit(int ret)
Definition: posix_main.cpp:80
void Posix_SetExit(int ret)
Definition: posix_main.cpp:109
idCommon * common
Definition: Common.cpp:206
#define NULL
Definition: Lib.h:88
#define context
Definition: getdate.c:236
void Posix_ClearSigs()
void Posix_InitSigs()
const char * Sys_GetCallStackCurStr(int depth)
Definition: stack.cpp:120
void Sys_SetFatalError(const char *error)
const int siglist[]
virtual void Quit(void)=0