From 25864910174cbedca7c5f039d9b269927b5e8a4d Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 18 May 2016 06:37:37 -0700 Subject: New functions: at-exit-call and at-exit-do-not-call. * sysif.c (at_exit_list): New static variable. (at_exit_call, at_exit_do_not_call): New functions. (at_exit_handler): New static function. (sysif_init): GC-protect at_exit_list. Register at_exit_handler with C atexit function. Register intrinsic functions at-exit-call and at-exit-do-not-call. * sysif.h (at_exit_call, at_exit_do_not_call): Registered. * txr.1: Documented. --- sysif.c | 29 +++++++++++++++++++++++++++++ sysif.h | 2 ++ txr.1 | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/sysif.c b/sysif.c index 141b2908..78327b0c 100644 --- a/sysif.c +++ b/sysif.c @@ -98,6 +98,8 @@ val passwd_s, gecos_s, dir_s, shell_s; val group_s, mem_s; #endif +static val at_exit_list; + static val errno_wrap(val newval) { val oldval = num(errno); @@ -130,6 +132,27 @@ static val exit_wrap(val status) return nil; } +val at_exit_call(val func) +{ + push(func, &at_exit_list); + return func; +} + +val at_exit_do_not_call(val func) +{ + val old = at_exit_list; + at_exit_list = remq(func, old); + return tnil(old == at_exit_list); +} + +static void at_exit_handler(void) +{ + val iter; + + for (iter = at_exit_list; iter; iter = cdr(iter)) + funcall(car(iter)); +} + static val abort_wrap(void) { abort(); @@ -1389,6 +1412,10 @@ static val fnmatch_wrap(val pattern, val string, val flags) void sysif_init(void) { + prot1(&at_exit_list); + + atexit(at_exit_handler); + stat_s = intern(lit("stat"), user_package); dev_k = intern(lit("dev"), keyword_package); ino_k = intern(lit("ino"), keyword_package); @@ -1444,6 +1471,8 @@ void sysif_init(void) reg_fun(intern(lit("errno"), user_package), func_n1o(errno_wrap, 0)); reg_fun(intern(lit("exit"), user_package), func_n1(exit_wrap)); + reg_fun(intern(lit("at-exit-call"), user_package), func_n1(at_exit_call)); + reg_fun(intern(lit("at-exit-do-not-call"), user_package), func_n1(at_exit_do_not_call)); reg_fun(intern(lit("abort"), user_package), func_n0(abort_wrap)); reg_fun(intern(lit("usleep"), user_package), func_n1(usleep_wrap)); #if HAVE_UNISTD_H diff --git a/sysif.h b/sysif.h index 62712387..5b22ea5c 100644 --- a/sysif.h +++ b/sysif.h @@ -43,6 +43,8 @@ typedef long off_t; #endif val getenv_wrap(val name); +val at_exit_call(val func); +val at_exit_do_not_call(val func); #if HAVE_FORK_STUFF val exec_wrap(val file, val args_opt); #endif diff --git a/txr.1 b/txr.1 index 7dd08b90..cb16a7f5 100644 --- a/txr.1 +++ b/txr.1 @@ -36279,6 +36279,44 @@ signal, known in \*(TX as the variable. Abnormal termination of the process is this signal's default action. +.coNP Functions @ at-exit-call and @ at-exit-do-not-call +.synb +.mets (at-exit-call << function ) +.mets (at-exit-do-not-call << function ) +.syne +.desc +The +.code at-exit-call +function registers +.meta function +to be called when the process terminates normally. +Multiple functions can be registered, and the same function +can be registered more than once. The registered +functions are called in reverse order of their +registrations. + +The +.code at-exit-do-not-call +function removes all previous +.code at-exit-call +registrations of +.metn function . + +The +.code at-exit-call +function returns +.metn function . + +The +.code at-exit-do-not-call +function returns +.code t +if it removed anything, +.code nil +if no registrations of +.meta function +were found. + .coNP Function @ usleep .synb .mets (usleep << usec ) -- cgit v1.2.3