2 * <signal.h> wrapper functions.
5 * Jonathan Pryor (jonpryor@vt.edu)
6 * Jonathan Pryor (jpryor@novell.com)
8 * Copyright (C) 2004-2005 Jonathan Pryor
9 * Copyright (C) 2008 Novell, Inc.
17 #ifndef PLATFORM_WIN32
19 #include <sys/types.h>
24 #include <mono/io-layer/atomic.h>
29 typedef void (*mph_sighandler_t
)(int);
30 typedef struct Mono_Unix_UnixSignal_SignalInfo signal_info
;
33 Mono_Posix_Stdlib_SIG_DFL (void)
39 Mono_Posix_Stdlib_SIG_ERR (void)
45 Mono_Posix_Stdlib_SIG_IGN (void)
51 Mono_Posix_Stdlib_InvokeSignalHandler (int signum
, void *handler
)
53 mph_sighandler_t _h
= (mph_sighandler_t
) handler
;
57 #ifndef PLATFORM_WIN32
59 #ifdef WAPI_ATOMIC_ASM
60 #define mph_int_get(p) InterlockedExchangeAdd ((p), 0)
61 #define mph_int_inc(p) InterlockedIncrement ((p))
62 #define mph_int_set(p,o,n) InterlockedExchange ((p), (n))
63 #elif GLIB_CHECK_VERSION(2,4,0)
64 #define mph_int_get(p) g_atomic_int_get ((p))
65 #define mph_int_inc(p) do {g_atomic_int_inc ((p));} while (0)
66 #define mph_int_set(p,o,n) do { \
67 while (!g_atomic_int_compare_and_exchange ((p), (o), (n))) {} \
70 #define mph_int_get(p) (*(p))
71 #define mph_int_inc(p) do { (*(p))++; } while (0)
72 #define mph_int_set(p,o,n) do { *(p) = n; } while (0)
76 Mono_Posix_Syscall_psignal (int sig
, const char* s
)
80 return errno
== 0 ? 0 : -1;
83 #define NUM_SIGNALS 64
84 static signal_info signals
[NUM_SIGNALS
];
87 default_handler (int signum
)
90 for (i
= 0; i
< NUM_SIGNALS
; ++i
) {
92 signal_info
* h
= &signals
[i
];
93 if (mph_int_get (&h
->signum
) != signum
)
95 mph_int_inc (&h
->count
);
96 fd
= mph_int_get (&h
->write_fd
);
104 static pthread_mutex_t signals_mutex
= PTHREAD_MUTEX_INITIALIZER
;
107 Mono_Unix_UnixSignal_install (int sig
)
110 signal_info
* h
= NULL
;
111 int have_handler
= 0;
114 mr
= pthread_mutex_lock (&signals_mutex
);
120 for (i
= 0; i
< NUM_SIGNALS
; ++i
) {
121 if (h
== NULL
&& signals
[i
].signum
== 0) {
123 h
->handler
= signal (sig
, default_handler
);
124 if (h
->handler
== SIG_ERR
) {
133 if (!have_handler
&& signals
[i
].signum
== sig
&&
134 signals
[i
].handler
!= default_handler
) {
136 handler
= signals
[i
].handler
;
138 if (h
&& have_handler
)
142 if (h
&& have_handler
) {
144 h
->handler
= handler
;
148 mph_int_set (&h
->count
, h
->count
, 0);
149 mph_int_set (&h
->signum
, h
->signum
, sig
);
152 pthread_mutex_unlock (&signals_mutex
);
158 count_handlers (int signum
)
162 for (i
= 0; i
< NUM_SIGNALS
; ++i
) {
163 if (signals
[i
].signum
== signum
)
170 Mono_Unix_UnixSignal_uninstall (void* info
)
175 mr
= pthread_mutex_lock (&signals_mutex
);
183 if (h
== NULL
|| h
< signals
|| h
> &signals
[NUM_SIGNALS
])
186 /* last UnixSignal -- we can unregister */
187 if (h
->have_handler
&& count_handlers (h
->signum
) == 1) {
188 mph_sighandler_t p
= signal (h
->signum
, h
->handler
);
197 pthread_mutex_unlock (&signals_mutex
);
203 setup_pipes (signal_info
** signals
, int count
, fd_set
*read_fds
, int *max_fd
)
206 for (i
= 0; i
< count
; ++i
) {
210 if ((r
= pipe (filedes
)) != 0) {
214 h
->read_fd
= filedes
[0];
215 h
->write_fd
= filedes
[1];
216 if (h
->read_fd
> *max_fd
)
217 *max_fd
= h
->read_fd
;
218 FD_SET (h
->read_fd
, read_fds
);
224 teardown_pipes (signal_info
** signals
, int count
)
227 for (i
= 0; i
< count
; ++i
) {
228 signal_info
* h
= signals
[i
];
231 if (h
->write_fd
!= 0)
239 wait_for_any (signal_info
** signals
, int count
, int max_fd
, fd_set
* read_fds
, int timeout
)
244 struct timeval
*ptv
= NULL
;
246 tv
.tv_sec
= timeout
/ 1000;
247 tv
.tv_usec
= (timeout
% 1000)*1000;
251 r
= select (max_fd
+ 1, read_fds
, NULL
, NULL
, ptv
);
252 } while (r
== -1 && errno
== EINTR
);
259 for (i
= 0; i
< count
; ++i
) {
260 signal_info
* h
= signals
[i
];
261 if (FD_ISSET (h
->read_fd
, read_fds
)) {
263 read (h
->read_fd
, &c
, 1); /* ignore any error */
274 * returns: -1 on error:
276 * index into _signals array of signal that was generated on success
279 Mono_Unix_UnixSignal_WaitAny (void** _signals
, int count
, int timeout
/* milliseconds */)
285 signal_info
** signals
= (signal_info
**) _signals
;
287 mr
= pthread_mutex_lock (&signals_mutex
);
295 r
= setup_pipes (signals
, count
, &read_fds
, &max_fd
);
297 r
= wait_for_any (signals
, count
, max_fd
, &read_fds
, timeout
);
299 teardown_pipes (signals
, count
);
301 pthread_mutex_unlock (&signals_mutex
);
306 #endif /* ndef PLATFORM_WIN32 */