hoshi-lang dev
Yet another programming language
Loading...
Searching...
No Matches
signal.cpp
Go to the documentation of this file.
2#include <csignal>
4
6
7// ---------------------------------------------------------
8// Windows Helper for SIGALRM Emulation
9// ---------------------------------------------------------
10#ifdef _WIN32
11// Global state for the simulated alarm timer
12static HANDLE hTimerQueue = NULL;
13static HANDLE hTimer = NULL;
14static runtime_signal_handler_bare_t g_alarm_handler = NULL;
15
16VOID CALLBACK WindowsAlarmCallback(PVOID lpParam, BOOLEAN TimerOrWaitFired) {
17 if (g_alarm_handler) {
18 g_alarm_handler(HS_SIGALRM);
19 }
20}
21
22void cleanup_win_timer() {
23 if (hTimer) {
24 DeleteTimerQueueTimer(hTimerQueue, hTimer, NULL);
25 hTimer = NULL;
26 }
27 if (hTimerQueue) {
28 DeleteTimerQueue(hTimerQueue);
29 hTimerQueue = NULL;
30 }
31}
32#endif
33
35 if (signum->value == HS_SIGKILL) {
36 // SIGKILL cannot be caught, blocked, or ignored on any platform.
38 err->type_id = 0;
39 err->gc_refcount = 1;
41 return err;
42 }
43
44 int type = -1;
45 switch (signum->value) {
46 case HS_SIGINT:
48 break;
49 case HS_SIGTERM:
51 break;
52 case HS_SIGALRM:
54 break;
55 default:
56 break;
57 }
58
59 if (type == -1) {
61 err->type_id = 0;
62 err->gc_refcount = 1;
64 return err;
65 }
66
67 runtime_signal_handler_info *info = (runtime_signal_handler_info *)malloc(sizeof(runtime_signal_handler_info)); // not YoiObject, use malloc
68 info->self = handler;
69 info->next = runtime_signal_handlers[type];
70 runtime_signal_handlers[type] = info;
71
73 success->type_id = 0;
74 success->gc_refcount = 1;
75 success->value = LIBSIG_SUCCESS;
76 return success;
77}
78
79LIBSIG_EXPORT int runtime_signal_alarm(unsigned int seconds) {
80#ifdef _WIN32
81 // Initialize Queue if needed
82 if (!hTimerQueue) {
83 hTimerQueue = CreateTimerQueue();
84 if (!hTimerQueue) return LIBSIG_ERR_UNSUPPORTED;
85 }
86
87 // Clear existing timer if exists
88 if (hTimer) {
89 DeleteTimerQueueTimer(hTimerQueue, hTimer, NULL);
90 hTimer = NULL;
91 }
92
93 // If seconds is 0, we just wanted to cancel (done above)
94 if (seconds == 0) {
95 return 0; // equivalent to returning remaining seconds, simplified here to 0
96 }
97
98 // Create new timer
99 // seconds * 1000 for milliseconds
100 if (!CreateTimerQueueTimer(&hTimer, hTimerQueue,
101 (WAITORTIMERCALLBACK)WindowsAlarmCallback,
102 NULL, seconds * 1000, 0, WT_EXECUTEONLYONCE)) {
104 }
105
106 return 0;
107#else
108 // POSIX Implementation
109 return alarm(seconds);
110#endif
111}
112
114 // Special handling for SIGKILL
115 if (signum == HS_SIGKILL) {
116#ifdef _WIN32
117 // Windows doesn't strictly support raising SIGKILL via raise(),
118 // so we force termination.
119 TerminateProcess(GetCurrentProcess(), 1);
120 return LIBSIG_SUCCESS; // Unreachable, strictly speaking
121#else
122 kill(getpid(), SIGKILL);
123 return LIBSIG_SUCCESS;
124#endif
125 }
126
127#ifdef _WIN32
128 // Windows raise() doesn't support custom signals like our emulated ALRM
129 if (signum == HS_SIGALRM) {
130 if (g_alarm_handler) {
131 g_alarm_handler(HS_SIGALRM);
132 return LIBSIG_SUCCESS;
133 }
135 }
136#endif
137
138 if (raise(signum) != 0) {
140 }
141 return LIBSIG_SUCCESS;
142}
143
145 if (signum == HS_SIGKILL) return LIBSIG_ERR_CANT_CATCH_KILL;
146
147#ifdef _WIN32
148 if (signum == HS_SIGALRM) {
151 if (--runtime_signal_handlers[HANDLER_TYPE_SIGALRM]->self->gc_refcount == 0) {
152 if (runtime_signal_handlers[HANDLER_TYPE_SIGALRM]->self->gc_dec_func) {
154 }
156 }
158 }
159 return LIBSIG_SUCCESS;
160 }
161#endif
162
163 while (runtime_signal_handlers[signum]) {
164 auto next = runtime_signal_handlers[signum]->next;
165 if (--runtime_signal_handlers[signum]->self->gc_refcount == 0) {
166 if (runtime_signal_handlers[signum]->self->gc_dec_func) {
167 runtime_signal_handlers[signum]->self->gc_dec_func(runtime_signal_handlers[signum]->self->this_ptr);
168 }
170 }
171 runtime_signal_handlers[signum] = next;
172 }
173
174 return LIBSIG_SUCCESS;
175}
176
178 if (signum == HS_SIGKILL) return LIBSIG_ERR_CANT_CATCH_KILL;
179
180#ifdef _WIN32
181 if (signum == HS_SIGALRM) {
182 g_alarm_handler = NULL; // If we clear the handler, the timer fires but does nothing
183 return LIBSIG_SUCCESS;
184 }
185#endif
186
187 if (signal(signum, SIG_IGN) == SIG_ERR) {
189 }
190 return LIBSIG_SUCCESS;
191}
192
193void runtime_signal_handler(int signum) {
195 signum_obj->type_id = 0;
196 signum_obj->gc_refcount = 1;
197 signum_obj->value = signum;
198
199 switch (signum) {
200 case HS_SIGINT:
202 info->self->handler((YoiObject *)info->self->this_ptr, signum_obj);
203 }
204 break;
205 case HS_SIGTERM:
207 info->self->handler((YoiObject *)info->self->this_ptr, signum_obj);
208 }
209 break;
210 case HS_SIGALRM:
212 info->self->handler((YoiObject *)info->self->this_ptr, signum_obj);
213 }
214 break;
215 default:
216 break;
217 }
218}
219
221 // Install our signal handler
222 #ifdef _WIN32
223 g_alarm_handler = runtime_signal_handler;
224 #else
227 signal(SIGPIPE, SIG_IGN);
228 #endif
229 signal(SIGINT, runtime_signal_handler);
230 signal(SIGTERM, runtime_signal_handler);
231}
void * runtime_object_alloc(unsigned long size)
Definition memory.cpp:96
void runtime_finalize_object(YoiObject *object)
Definition memory.cpp:90
void runtime_signal_handler(int signum)
Definition signal.cpp:193
LIBSIG_EXPORT int runtime_signal_ignore(int signum)
Definition signal.cpp:177
LIBSIG_EXPORT YoiIntegerObject * runtime_signal_register(YoiIntegerObject *signum, YoiVoidIntCallableInterface *handler)
Definition signal.cpp:34
LIBSIG_EXPORT void runtime_signal_init()
Definition signal.cpp:220
LIBSIG_EXPORT int runtime_signal_alarm(unsigned int seconds)
Definition signal.cpp:79
runtime_signal_handler_info * runtime_signal_handlers[3]
Definition signal.cpp:5
LIBSIG_EXPORT int runtime_signal_raise(int signum)
Definition signal.cpp:113
LIBSIG_EXPORT int runtime_signal_default(int signum)
Definition signal.cpp:144
#define LIBSIG_ERR_REGISTER_FAIL
Definition signal.h:27
#define HANDLER_TYPE_SIGALRM
Definition signal.h:39
#define LIBSIG_EXPORT
Definition signal.h:23
#define HS_SIGTERM
Definition signal.h:33
#define HANDLER_TYPE_SIGINT
Definition signal.h:37
void(* runtime_signal_handler_bare_t)(int signum)
Definition signal.h:41
#define LIBSIG_ERR_UNSUPPORTED
Definition signal.h:28
#define HS_SIGINT
Definition signal.h:32
#define LIBSIG_SUCCESS
Definition signal.h:26
#define HS_SIGALRM
Definition signal.h:34
#define HANDLER_TYPE_SIGTERM
Definition signal.h:38
#define LIBSIG_ERR_RAISE_FAIL
Definition signal.h:30
#define LIBSIG_INTERNAL_ALRM
Definition signal.h:19
#define LIBSIG_ERR_CANT_CATCH_KILL
Definition signal.h:29
#define HS_SIGKILL
Definition signal.h:35
#define LIBSIG_INTERNAL_KILL
Definition signal.h:20
unsigned long long gc_refcount
Definition memory.h:26
unsigned long long type_id
Definition memory.h:27
long long value
Definition memory.h:28
void *(* gc_dec_func)(void *this_ptr)
Definition signal.h:49
runtime_signal_handler_info * next
Definition signal.h:55
YoiVoidIntCallableInterface * self
Definition signal.h:54