NAME ^

src/exit.c - Exit Handling

DESCRIPTION ^

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.

Functions ^

*/

#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);
}

/*

SEE ALSO ^

include/parrot/exit.h and t/src/exit.t.

HISTORY ^

Initial version by Josh Wilmes.

*/

/* * Local variables: * c-file-style: "parrot" * End: * vim: expandtab shiftwidth=4: */


parrot