HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_Signal.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT library (C++)
7  *
8  * COMMENTS: Wrapper on signal handlers.
9  * By instantiating an object of this type, the signal
10  * handler is set to the desired value. When this
11  * object is destructed, the signals are automatically
12  * returned to their previous values.
13  *
14  * NOTES: Since the constructor/destructor handle installing
15  * and removal of the signals, this can even be used
16  * within a block of code to allow signals to be caught
17  * temporarily.
18  * When installing signals permanently, it is suggested
19  * that signal(2) still be used. However, it is possible
20  * to use the static "override" method below.
21  */
22 
23 #ifndef __UT_Signal_h__
24 #define __UT_Signal_h__
25 
26 #include "UT_API.h"
27 
28 #include "UT_Array.h"
29 
30 #include <signal.h> // Get a list of signals for us please
31 
32 #if defined(WIN32)
33  // define all the signals not already defined by NT.
34  // Removed two signals that conflicted with defined NT signals.
35  // Reserved signal #'s on NT so far are: 2,4,8,11,15,21,22
36  // Please note that addSignal will silently ignore any non-handled
37  // windows handlers as the runtime library does parameter validation
38  // and rejects them.
39  #define SIGHUP 1
40  // WIN32: SIGINT 2
41  #define SIGQUIT 3
42  // WIN32: SIGILL 4
43  #define SIGTRAP 5 // Unhandled
44  #define SIGEMT 7 // Unhandled
45  // WIN32: SIGFPE 8
46  #define SIGKILL 9 // Unhandled
47  #define SIGBUS 10 // Unhandled
48  // WIN32: SIGSEGV 11
49  #define SIGSYS 12 // Unhandled
50  #define SIGPIPE 13
51  #define SIGALRM 14 // Unhandled
52  // WIN32: SIGTERM 15
53  #define SIGUSR1 16 // Windows: IOINT?
54  #define SIGUSR2 17 // Windows: STOP?
55  // do not use SIGCLD anymore! provided here for backwards
56  // compatibility only!
57  #define SIGCLD 18 // Unhandled
58  // SIGCCHLD is the new POSIX name for SIGCLD, use this instead
59  #define SIGCHLD 18 // Unhandled
60  #define SIGPWR 19 // Unhandled
61  #define SIGWINCH 20 // Unhandled
62  // WIN32: SIGBREAK 21
63  // It's probably ok that SIGURG (urgent socket condition) is handled the
64  // same as SIGBREAK since there's no such thing on NT
65  #define SIGURG 21
66  // WIN32: SIGABRT 22
67  #define SIGSTOP 23 // Unhandled
68  #define SIGTSTP 24 // Unhandled
69  #define SIGCONT 25 // Unhandled
70  #define SIGTTIN 26 // Unhandled
71  #define SIGTTOU 27 // Unhandled
72  #define SIGVTALRM 28 // Unhandled
73  #define SIGPROF 29 // Unhandled
74  #define SIGXCPU 30 // Unhandled
75  #define SIGXFSZ 31 // Unhandled
76  #define SIG32 32 // Unhandled
77  // According to Irix it supports all signal numbers between 0 and 64
78  // So all other signals should probably start at 65
79  #define SIGPOLL 65 // Unhandled
80 
81  #define sigset(a,b) signal(a,b)
82 #else
83 
84 #if !defined(SIGEMT)
85 #if defined(SIGUNUSED)
86 #define SIGEMT SIGUNUSED
87 #else
88 #define SIGEMT SIGBUS
89 #endif
90 #endif
91 
92 #if !defined(SIGSYS)
93 #if defined(SIGUNUSED)
94 #define SIGSYS SIGUNUSED
95 #else
96 #define SIGSYS SIGBUS
97 #endif
98 #endif
99 
100 #endif
101 
102 #define UT_MAX_SIGNALS 64 // Allow for POSIX standard
103 
104 #if defined(LINUX) || defined(MBSD)
105 #define SUPPORTS_SIGINFO
106 #endif
107 
109 {
110 public:
111  UTsignalHandlerArg(int signal_num)
112  : mySignalNum(signal_num),
113  myOpaqueCPUContext(0),
114  myDepthFromSignalHandler(0)
115  {}
116  ~UTsignalHandlerArg() = default;
117 
118  /// Increment the depth from the signal handler in the copy constructor.
119  /// That way, as the signal handler argument is passed from the signal
120  /// handler function to other functions, we'll know how far back up
121  /// in the stack the original signal handler function is.
123  : mySignalNum(sig_arg.mySignalNum),
124 #ifdef SUPPORTS_SIGINFO
125  mySignalInfo(sig_arg.mySignalInfo),
126 #endif
127  myOpaqueCPUContext(sig_arg.myOpaqueCPUContext),
128  myDepthFromSignalHandler(sig_arg.myDepthFromSignalHandler + 1),
129  myUserData(sig_arg.myUserData)
130  {}
131  UTsignalHandlerArg &operator=(const UTsignalHandlerArg &sig_arg) = delete;
132 
133  int getSignalNum() const { return mySignalNum; }
134 
135 #ifdef SUPPORTS_SIGINFO
136  void setSignalInfo(siginfo_t *signal_info)
137  {
138  mySignalInfo = signal_info;
139  }
140  const siginfo_t *getSignalInfo() const { return mySignalInfo; }
141 #endif
142  void setSignalContext(void *opaque_cpu_context)
143  {
144  myOpaqueCPUContext = opaque_cpu_context;
145  }
146  const void *getOpaqueCPUContext() const { return myOpaqueCPUContext; }
147 
149  { return myDepthFromSignalHandler; }
150 
151  void setUserData(void* user_data) { myUserData = user_data; }
152  void *userData() { return myUserData; }
153 private:
154  void *myUserData = nullptr;
155  int mySignalNum;
156  void *myOpaqueCPUContext;
157  int myDepthFromSignalHandler;
158 #ifdef SUPPORTS_SIGINFO
159  siginfo_t *mySignalInfo;
160 #endif
161 };
162 
163 
165 
166 #if !defined(LINUX) && !defined(MBSD)
167 extern "C"
168 #endif
170 
172 {
173 public:
174  class Empty
175  {
176  };
177 
178  /// Catch a specified signal. If signum <= 0, then all signals
179  /// (except ABRT) are caught. There are two styles of constructors.
180  /// One takes an old-style signal handler that is needed so we can easily
181  /// specify SIG_DFL, SIG_IGN, and SIG_ERR as the signal behaviours. The
182  /// other constructor takes our own data structure as an argument and is
183  /// designed to support the SA_SIGINFO 3-argument style callback added in
184  /// POSIX.1b.
185  /// If ignore_prev is false, all other signal handlers for the raised
186  /// signal will be called in the reverse order they were installed.
187  /// Otherwise, only the last handler for this signal will be called.
188  explicit UT_Signal(int signum=0, UToldStyleSigHandler handler = SIG_DFL,
189  bool ignore_prev=false);
190  explicit UT_Signal(int signum, UTsigHandler handler,
191  bool ignore_prev=false,
192  void* user_data = nullptr);
193  /// This constructor is used when the signals that we want to catch are
194  /// unknown at the time the signal object is created.
195  explicit UT_Signal(const Empty& );
196 
197  /// Catch a specified set of signals. The first argument is an
198  /// array of signal numbers to catch. The array should be
199  /// null terminated (since there is no signal 0)
200  template <std::size_t Size>
201  UT_Signal(const int (&signums)[Size], UToldStyleSigHandler handler = SIG_DFL,
202  bool ignore_prev=false)
203  {
204  constructPriv(signums, Size, handler, ignore_prev, nullptr);
205  }
206  template <std::size_t Size>
207  UT_Signal(const int (&signums)[Size], UTsigHandler handler,
208  bool ignore_prev=false,
209  void* user_data = nullptr)
210  {
211  constructPriv(signums, Size, handler, ignore_prev, user_data);
212  }
213  explicit UT_Signal(const UT_Array<int> &signums, UTsigHandler handler,
214  bool ignore_prev = false,
215  void *user_data = nullptr);
216  explicit UT_Signal(const UT_Array<int> &signums,
217  UToldStyleSigHandler handler = SIG_DFL,
218  bool ignore_prev = false);
219  /// Destructing will restore the signals to their previous values.
220  ~UT_Signal();
221 
222  UT_Signal(const UT_Signal &) = delete;
223  UT_Signal &operator=(const UT_Signal &) = delete;
224 
225  /// The following method is made available to override the default
226  /// handler without destructing the object. For example, in the
227  /// signal handler, you may want to ignore further signals of a certain
228  /// type. This method allows you to set the signals. In fact, it
229  /// simply calls sigaction() with the new handler.
230  void override(int signum, UToldStyleSigHandler,
231  bool ignore_prev=false);
232  void override(int signum, UTsigHandler,
233  bool ignore_prev=false,
234  void* user_data = nullptr);
235 
236  /// Remove a specific signal
237  void removeSignal(int sig);
238 
239  /// This disables the cant return behaviour used in UT_Signal. This
240  /// behaviour will abort the application on behalf of the application
241  /// itself for signals that it treats as cant return (i.e. SIGTERM). For
242  /// some applications the application needs to control the full shutdown
243  /// otherwise the application can end up erroring on exit.
244  static void disableCantReturn(bool disable);
245 
246 private:
247  /// This class keeps track of a signal handler callback that is either
248  /// an old-style callback (one that accepts an int, like SIG_DFL or
249  /// SIG_IGN) or a new-style callback (one that accepts a UTsignalHandlerArg).
250  class UT_API UT_ComboSignalHandler
251  {
252  public:
253  UT_ComboSignalHandler();
254  UT_ComboSignalHandler(UTsigHandler handler);
255  UT_ComboSignalHandler(UToldStyleSigHandler handler);
256 
257  UT_ComboSignalHandler &operator=(UTsigHandler handler);
258  UT_ComboSignalHandler &operator=(UToldStyleSigHandler handler);
259  bool operator!=(UToldStyleSigHandler handler) const;
260 
261  bool isSet() const;
262  void operator()(int signal_num,
263 #ifdef SUPPORTS_SIGINFO
264  siginfo_t *signal_info,
265 #endif
266  void *opaque_cpu_context) const;
267  void setUserData(void *user_data) { myUserData = user_data; }
268  void reset()
269  {
270  mySigHandler.myNewStyle = nullptr;
271  myUserData = nullptr;
272  }
273 
274  private:
275  union
276  {
277  UTsigHandler myNewStyle;
278  UToldStyleSigHandler myOldStyle;
279  } mySigHandler;
280  bool myIsOldStyleSigHandler;
281  void *myUserData = nullptr;
282  };
283 
284  void constructPriv(int signum,
285  UT_ComboSignalHandler handler,
286  bool ignore_prev,
287  void* user_data);
288  void constructPriv(const int signums[],
289  const std::size_t size,
290  UT_ComboSignalHandler handler,
291  bool ignore_prev,
292  void* user_data);
293  void addSignal(int signum, UT_ComboSignalHandler handler,
294  bool ignore_prev);
295  void removeSignal_(int signum);
296  void updateActuals();
297  void overridePriv(int signum,
298  UT_ComboSignalHandler handler,
299  bool ignore_prev);
300  void init_();
301 
302  static void processSignal(int signal_num
303 #ifdef SUPPORTS_SIGINFO
304  , siginfo_t *, void *
305 #endif
306  );
307 
308  UT_ComboSignalHandler mySignals[UT_MAX_SIGNALS];
309  bool myIgnorePrev[UT_MAX_SIGNALS];
310 
311  UT_Signal *myNext = nullptr, *myPrev = nullptr;
312 };
313 
314 #endif
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
void * userData()
Definition: UT_Signal.h:152
int getSignalNum() const
Definition: UT_Signal.h:133
void
Definition: png.h:1083
void(* UToldStyleSigHandler)(int)
Definition: UT_Signal.h:169
UT_Signal(const int(&signums)[Size], UToldStyleSigHandler handler=SIG_DFL, bool ignore_prev=false)
Definition: UT_Signal.h:201
#define UT_API
Definition: UT_API.h:14
UTsignalHandlerArg(int signal_num)
Definition: UT_Signal.h:111
UT_Signal(const int(&signums)[Size], UTsigHandler handler, bool ignore_prev=false, void *user_data=nullptr)
Definition: UT_Signal.h:207
GLboolean reset
Definition: glad.h:5138
#define UT_MAX_SIGNALS
Definition: UT_Signal.h:102
GLsizeiptr size
Definition: glcorearb.h:664
void setUserData(void *user_data)
Definition: UT_Signal.h:151
void setSignalContext(void *opaque_cpu_context)
Definition: UT_Signal.h:142
UTsignalHandlerArg(const UTsignalHandlerArg &sig_arg)
Definition: UT_Signal.h:122
bool operator!=(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:165
void(* UTsigHandler)(UTsignalHandlerArg)
Definition: UT_Signal.h:164
const void * getOpaqueCPUContext() const
Definition: UT_Signal.h:146
int getDepthFromSignalHandler() const
Definition: UT_Signal.h:148