-
Notifications
You must be signed in to change notification settings - Fork 138
/
exit.c
252 lines (179 loc) · 5.89 KB
/
exit.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
Copyright (C) 2001-2010, Parrot Foundation.
=head1 NAME
src/exit.c - Exit Handling
=head1 DESCRIPTION
Parrot's version of C<exit()>, C<on_exit()>, and friends.
C<Parrot_x_on_exit()> allows you register exit handlers which will be
called by C<Parrot_x_exit()> when the interpreter exits.
=head2 Functions
=over 4
=cut
*/
#include <stdlib.h>
#include "parrot/parrot.h"
/* HEADERIZER HFILE: include/parrot/exit.h */
/*
=item C<void Parrot_x_on_exit(PARROT_INTERP, exit_handler_f function, void
*arg)>
Register the specified function to be called on interpreter exit.
=cut
*/
PARROT_EXPORT
void
Parrot_x_on_exit(PARROT_INTERP, ARGIN(exit_handler_f function), ARGIN_NULLOK(void *arg))
{
ASSERT_ARGS(Parrot_x_on_exit)
handler_node_t * const new_node = mem_internal_allocate_typed(handler_node_t);
new_node->function = function;
new_node->arg = arg;
new_node->next = interp->exit_handler_list;
interp->exit_handler_list = new_node;
}
/*
=item C<void Parrot_x_jump_out(NULLOK_INTERP, int status)>
Jumps out returning to the caller api function. Do not execute registered
on-exit handlers. If an interpreter is not provided, or if the interpreter
does not have a jump buffer registered, force an exit back to the system
(which may be very bad for the client application).
=cut
*/
PARROT_EXPORT
PARROT_DOES_NOT_RETURN
PARROT_COLD
void
Parrot_x_jump_out(NULLOK_INTERP, int status)
{
ASSERT_ARGS(Parrot_x_jump_out)
if (interp && interp->api_jmp_buf)
longjmp(*(interp->api_jmp_buf), 1);
else
PARROT_FORCE_EXIT(status);
}
/*
=item C<void Parrot_x_exit(PARROT_INTERP, int status)>
Normal interpreter exit. Execute any registered exit handlers and jump back
out to the last API call-in routine.
=cut
*/
PARROT_EXPORT
PARROT_DOES_NOT_RETURN
PARROT_COLD
void
Parrot_x_exit(PARROT_INTERP, int status)
{
ASSERT_ARGS(Parrot_x_exit)
Parrot_x_execute_on_exit_handlers(interp, status);
Parrot_x_jump_out(interp, status);
}
/*
=item C<void Parrot_x_execute_on_exit_handlers(PARROT_INTERP, int status)>
Execute all registered on-exit callback functions. This must be done before
the interpreter is destroyed.
=cut
*/
PARROT_COLD
PARROT_NO_ADDRESS_SAFETY_ANALYSIS
void
Parrot_x_execute_on_exit_handlers(PARROT_INTERP, int status)
{
ASSERT_ARGS(Parrot_x_execute_on_exit_handlers)
/* call all the exit handlers */
handler_node_t *node;
node = interp->exit_handler_list;
/* Block GC. We don't want any shenanigans while we are executing our
callbacks */
Parrot_block_GC_mark(interp);
Parrot_block_GC_sweep(interp);
while (node) {
handler_node_t * const next = node->next;
(node->function)(interp, status, node->arg);
mem_internal_free(node);
node = next;
}
/* It could be that the interpreter already is destroyed. See issue 765 */
interp->exit_handler_list = NULL;
interp->final_exception = NULL;
/* Re-enable GC, which we will want if GC finalizes */
Parrot_unblock_GC_mark(interp);
Parrot_unblock_GC_sweep(interp);
}
/*
=item C<void Parrot_x_force_error_exit(NULLOK_INTERP, int exitcode,
ARGIN_FORMAT(const char * format), ...)>
Error handler of last resort, under normal circumstances. Print out an error
message to C<stderr> and exit from the interpreter. If possible attempt to
jump out of libparrot. If not, hard exit back to the system.
=cut
*/
PARROT_DOES_NOT_RETURN
PARROT_COLD
void
Parrot_x_force_error_exit(NULLOK_INTERP, int exitcode, ARGIN_FORMAT(const char * format), ...)
{
ASSERT_ARGS(Parrot_x_force_error_exit)
va_list arglist;
va_start(arglist, format);
vfprintf(stderr, format, arglist);
fprintf(stderr, "\n");
fflush(stderr);
va_end(arglist);
Parrot_x_jump_out(interp, exitcode);
}
/*
=item C<void Parrot_x_panic_and_exit(NULLOK_INTERP, const char *message, const
char *file, unsigned int line)>
Panic handler. Things have gone very wrong in an unexpected way. Print out an
error message and instructions for the user to report the error to the
developers. Perform a full core dump and force exit back to the system.
=cut
*/
PARROT_EXPORT
PARROT_DOES_NOT_RETURN
PARROT_COLD
void
Parrot_x_panic_and_exit(NULLOK_INTERP, ARGIN_NULLOK(const char *message),
ARGIN_NULLOK(const char *file), unsigned int line)
{
ASSERT_ARGS(Parrot_x_panic_and_exit)
/* Note: we can't format any floats in here--Parrot_sprintf
** may panic because of floats.
** and we don't use Parrot_sprintf or such, because we are
** already in panic --leo
*/
fprintf(stderr, "Parrot VM: PANIC: %s!\n",
message ? message : "(no message available)");
fprintf(stderr, "C file %s, line %u\n",
file ? file : "(not available)", line);
fprintf(stderr, "Parrot file (not available), ");
fprintf(stderr, "line (not available)\n");
fprintf(stderr, "\n\
We highly suggest you notify the Parrot team if you have not been working on\n\
Parrot. Use parrotbug (located in parrot's root directory) or send an\n\
e-mail to parrot-dev@lists.parrot.org.\n\
Include the entire text of this error message and the text of the script that\n\
generated the error. If you've made any modifications to Parrot, please\n\
describe them as well.\n\n");
fprintf(stderr, "Version : %s\n", PARROT_VERSION);
fprintf(stderr, "Configured : %s\n", PARROT_CONFIG_DATE);
fprintf(stderr, "Architecture: %s\n", PARROT_ARCHNAME);
if (interp)
fprintf(stderr, "Interp Flags: %#x\n", (unsigned int)interp->flags);
else
fprintf(stderr, "Interp Flags: (no interpreter)\n");
fprintf(stderr, "Exceptions : %s\n", "(missing from core)");
fprintf(stderr, "\nDumping Core...\n");
DUMPCORE();
}
/*
=back
=head1 SEE ALSO
F<include/parrot/exit.h> and F<t/src/exit.t>.
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/