parrotcode: Exit Handling | |
Contents | C |
src/exit.c - Exit Handling
Parrot's version of exit()
,
on_exit()
,
and friends.
Parrot_on_exit()
allows you register exit handlers which will be called by Parrot_exit()
when the interpreter exits.
*/
#include <stdlib.h> #include "parrot/parrot.h"
/* HEADERIZER HFILE: include/parrot/exit.h */
/*
FUNCDOC: Parrot_on_exit
Register the specified function to be called on exit.
*/
PARROT_API void Parrot_on_exit(PARROT_INTERP, NOTNULL(exit_handler_f function), NULLOK(void *arg)) { /* XXX we might want locking around the list access. I'm sure this * will be the least of the threading issues. */
handler_node_t* const new_node = mem_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;
}
/*
FUNCDOC: Parrot_exit
Exit, calling any registered exit handlers.
*/
PARROT_API PARROT_DOES_NOT_RETURN void Parrot_exit(PARROT_INTERP, int status) { /* call all the exit handlers */ /* we are well "below" the runloop now, where lo_var_ptr * is set usually - exit handlers may run some resource-hungry * stuff like printing profile stats - a DOD run would kill * resources - TODO reset stacktop or better disable GC */ /* * we don't allow new exit_handlers being installed inside exit handlers * - do we? * and: interp->exit_handler_list is gone, after the last exit handler * (Parrot_really_destroy) has run */ handler_node_t *node = interp->exit_handler_list;
Parrot_block_DOD(interp);
Parrot_block_GC(interp);
while (node) {
handler_node_t * const next = node->next;
(node->function)(interp, status, node->arg);
mem_sys_free(node);
node = next;
}
exit(status);
}
/*
include/parrot/exit.h and t/src/exit.t.
Initial version by Josh Wilmes.
*/
/* * Local variables: * c-file-style: "parrot" * End: * vim: expandtab shiftwidth=4: */
|