lib: intro module to manage C signals
[nit.git] / lib / signals / signals.nit.c
1 /* This file is part of NIT ( http://www.nitlanguage.org ).
2 *
3 * Copyright 2011 Alexis Laferrière <alexis.laf@xymus.net>
4 *
5 * This file is free software, which comes along with NIT. This software is
6 * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 * PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 * is kept unaltered, and a notification of the changes is added.
10 * You are allowed to redistribute it and sell it, alone or is a part of
11 * another product.
12 */
13
14 #undef _POSIX_SOURCE
15 #define _POSIX_SOURCE 1
16 #include <signal.h>
17 #include <stdio.h>
18
19 #include "signals.nit.h"
20
21 /*
22 Structure to manage each possible signals
23 are used in an array of 32 maximum signals.
24 This array is global to the software.
25 */
26 struct nit_signals_ent {
27 char raised; /* !=0 if has been raised */
28 SignalHandler handler; /* instance to receive call */
29 char safely; /* if !=0 then manage signal safely, otherwise react when raised */
30 } nit_signals_list[32] = {0x0};
31
32 /* Receiver to all signals
33 If unsafe, it calls directly the Nit receiver,
34 otherwise it marks the signal as raised and returns.
35 */
36 void receiver( int sig )
37 {
38 if ( sig < 32 && sig >=0 )
39 {
40 if ( nit_signals_list[sig].safely ) {
41 nit_signals_list[ sig ].raised += 1;
42 } else {
43 SignalHandler_receive_signal( nit_signals_list[ sig ].handler, sig );
44 }
45 }
46 }
47
48 /*
49 C implementation of signals::SignalHandler::handle_signal
50
51 Imported methods signatures:
52 void SignalHandler_receive_signal( SignalHandler recv, bigint signal ) for signals::SignalHandler::receive_signal
53 */
54 void SignalHandler_handle_signal___impl( SignalHandler recv, bigint signal, int safely )
55 {
56 if ( signal < 32 && signal >=0 ) {
57 struct sigaction act;
58 sigemptyset(&act.sa_mask);
59 act.sa_flags = 0;
60 act.sa_handler = receiver;
61
62 sigaction(signal, &act, NULL);
63
64 SignalHandler last_handler = nit_signals_list[signal].handler;
65 if ( last_handler != NULL )
66 SignalHandler_decr_ref( last_handler );
67
68 nit_signals_list[signal].handler = recv;
69 SignalHandler_incr_ref( recv );
70
71 nit_signals_list[signal].safely = safely;
72 }
73 }
74
75 /*
76 C implementation of signals::SignalHandler::ignore_signal
77 */
78 void SignalHandler_ignore_signal___impl( SignalHandler recv, bigint signal )
79 {
80 if ( signal < 32 && signal >=0 ) {
81 struct sigaction act;
82 sigemptyset(&act.sa_mask);
83 act.sa_flags = 0;
84 act.sa_handler = SIG_IGN;
85 sigaction(signal, &act, NULL);
86
87 SignalHandler last_handler = nit_signals_list[signal].handler;
88 if ( last_handler != NULL )
89 SignalHandler_decr_ref( last_handler );
90 }
91 }
92
93 /*
94 C implementation of signals::SignalHandler::default_signal
95 */
96 void SignalHandler_default_signal___impl( SignalHandler recv, bigint signal )
97 {
98 if ( signal < 32 && signal >=0 ) {
99 struct sigaction act;
100 sigemptyset(&act.sa_mask);
101 act.sa_flags = 0;
102 act.sa_handler = SIG_DFL;
103 sigaction(signal, &act, NULL);
104
105 SignalHandler last_handler = nit_signals_list[signal].handler;
106 if ( last_handler != NULL )
107 SignalHandler_decr_ref( last_handler );
108 }
109 }
110
111 void Object_set_alarm___impl( Object recv, bigint sec )
112 {
113 alarm( sec );
114 }
115
116 /*
117 C implementation of signals::Object::check_signals
118
119 Imported methods signatures:
120 void SignalHandler_receive_signal( SignalHandler recv, bigint signal ) for signals::SignalHandler::receive_signal
121 */
122 int Object_check_signals___impl( Object recv )
123 {
124 int sig;
125 int raised_something = 0;
126
127 for ( sig = 0; sig < 32; sig ++ )
128 if ( nit_signals_list[sig].raised ) {
129 nit_signals_list[sig].raised = 0;
130 raised_something = 1;
131 SignalHandler_receive_signal( nit_signals_list[sig].handler, sig );
132 }
133
134 return raised_something;
135 }