rcs_exit.cc
1 /******************************************************************** 2 * Description: rcs_exit.cc 3 * This module provides a portable way to make sure multiple 4 * functions are called before exiting. 5 * These functions should be written to take an int and return void. 6 * 7 * Derived from a work by Fred Proctor & Will Shackleford 8 * 9 * Author: 10 * License: LGPL Version 2 11 * System: Linux 12 * 13 * Copyright (c) 2004 All rights reserved. 14 * 15 * Last change: 16 ********************************************************************/ 17 18 /* Forward Function Prototypes */ 19 #include "rcs_exit.hh" 20 21 #include "linklist.hh" // LinkedList 22 #include "rcs_print.hh" // rcs_print_error() 23 #include "timer.hh" // esleep() 24 25 #ifdef __cplusplus 26 extern "C" { 27 #endif 28 29 #include <stdlib.h> // exit() 30 #include <signal.h> // signal() , SIGINT 31 32 #ifdef __cplusplus 33 } 34 #endif 35 36 static LinkedList *exit_list = (LinkedList *) NULL; 37 38 struct RCS_EXIT_LIST_ENTRY { 39 long process_id; 40 void (*fptr) (int); 41 }; 42 43 // NOTE -- 44 // the GNU VxWorks C++ cross-compiler (g++68k) has a bug, that 45 // prevents me from passing a pointer to a function as the first 46 // argument of a function. 47 48 int attach_rcs_exit_list(void (*fptr) (int)) 49 { 50 RCS_EXIT_LIST_ENTRY entry; 51 if (NULL == exit_list) { 52 exit_list = new LinkedList; 53 } 54 if (NULL == exit_list) { 55 rcs_print_error("attach_rcs_exit_list:: Out of Memory.\n"); 56 return -1; 57 } 58 entry.process_id = 0; 59 entry.fptr = fptr; 60 return exit_list->store_at_tail(&entry, sizeof(entry), 1); 61 } 62 63 void rcs_cleanup(int code) 64 { 65 RCS_EXIT_LIST_ENTRY *entry; 66 long process_id = 0; 67 68 if (NULL == exit_list) { 69 return; 70 } 71 entry = (RCS_EXIT_LIST_ENTRY *) exit_list->get_head(); 72 while (NULL != entry) { 73 if (entry->process_id == process_id && entry->fptr != NULL) { 74 entry->fptr(code); 75 } 76 entry = (RCS_EXIT_LIST_ENTRY *) exit_list->get_next(); 77 } 78 if (exit_list->list_size == 0) { 79 delete exit_list; 80 exit_list = (LinkedList *) NULL; 81 } 82 } 83 84 static int rcs_ready_for_exit = 0; 85 static int rcs_exit_sig = 0; 86 static void rcs_exit_signal_handler(int sig) 87 { 88 rcs_ready_for_exit = 1; 89 rcs_exit_sig = sig; 90 } 91 92 void rcs_exit(int code) 93 { 94 rcs_cleanup(code); 95 if (code == -1) { 96 rcs_print_error("\n Errors Reported!!!\n Press ^C to exit.\n"); 97 signal(SIGINT, rcs_exit_signal_handler); 98 int secs = 0; 99 while (!rcs_ready_for_exit && secs < 600) { 100 esleep(1.0); 101 secs++; 102 } 103 } 104 exit(code); 105 }