00001 /********************************************************************** 00002 * File: rcs_exit.cc 00003 * This module provides a portable way to make sure multiple 00004 * functions are called before exiting. 00005 * These functions should be written to take an int and return void. 00006 ***********************************************************************/ 00007 00008 /* Forward Function Prototypes */ 00009 #include "rcs_exit.hh" 00010 00011 00012 #include "rcs_defs.hh" // WINDOWS, 00013 #include "linklist.hh" //RCS_LINKED_LIST 00014 #include "rcs_prnt.hh" // rcs_print_error() 00015 #include "timer.hh" // esleep() 00016 00017 #ifdef EXTERN_C_STD_HEADERS 00018 extern "C" 00019 { 00020 #endif 00021 00022 #include <stdlib.h> // exit() 00023 #ifndef UNDER_CE 00024 #include <signal.h> // signal() , SIGINT 00025 #endif 00026 00027 #ifdef EXTERN_C_STD_HEADERS 00028 } 00029 #endif 00030 00031 #ifdef WINDOWS 00032 #include <windows.h> // GetCurrentProcessId() 00033 #endif 00034 00035 #ifdef VXWORKS 00036 #include <taskLib.h> // taskIdSelf() 00037 #endif 00038 00039 static RCS_LINKED_LIST *exit_list = (RCS_LINKED_LIST *) NULL; 00040 00041 struct RCS_EXIT_LIST_ENTRY 00042 { 00043 long process_id; 00044 void (*fptr) (int); 00045 }; 00046 00047 // NOTE -- 00048 // the GNU VxWorks C++ cross-compiler (g++68k) has a bug, that 00049 // prevents me from passing a pointer to a function as the first 00050 // argument of a function. 00051 #if defined(VXWORKS) && !defined(__CENTERLINE__) 00052 int RCS_EXPORT 00053 attach_rcs_exit_list (void *fptr) 00054 #else 00055 int RCS_EXPORT 00056 attach_rcs_exit_list (void (*fptr) (int)) 00057 #endif 00058 { 00059 RCS_EXIT_LIST_ENTRY entry; 00060 if (NULL == exit_list) 00061 { 00062 exit_list = new RCS_LINKED_LIST; 00063 } 00064 if (NULL == exit_list) 00065 { 00066 rcs_print_error ("attach_rcs_exit_list:: Out of Memory.\n"); 00067 return -1; 00068 } 00069 entry.process_id = 0; 00070 entry.fptr = fptr; 00071 #ifdef WINDOWS 00072 entry.process_id = ((long) GetCurrentProcessId ()); 00073 #endif 00074 #ifdef VXWORKS 00075 entry.process_id = (long) taskIdSelf (); 00076 #endif 00077 return exit_list->store_at_tail (&entry, sizeof (entry), 1); 00078 } 00079 00080 void RCS_EXPORT 00081 rcs_cleanup (int code) 00082 { 00083 RCS_EXIT_LIST_ENTRY *entry; 00084 long process_id = 0; 00085 #ifdef WINDOWS 00086 process_id = ((long) GetCurrentProcessId ()); 00087 #endif 00088 #ifdef VXWORKS 00089 process_id = (long) taskIdSelf (); 00090 #endif 00091 00092 if (NULL == exit_list) 00093 { 00094 return; 00095 } 00096 entry = (RCS_EXIT_LIST_ENTRY *) exit_list->get_head (); 00097 while (NULL != entry) 00098 { 00099 if (entry->process_id == process_id && entry->fptr != NULL) 00100 { 00101 entry->fptr (code); 00102 } 00103 entry = (RCS_EXIT_LIST_ENTRY *) exit_list->get_next (); 00104 } 00105 if (exit_list->list_size == 0) 00106 { 00107 delete exit_list; 00108 exit_list = (RCS_LINKED_LIST *) NULL; 00109 } 00110 } 00111 00112 static int rcs_ready_for_exit = 0; 00113 static int rcs_exit_sig = 0; 00114 static void 00115 rcs_exit_signal_handler (int sig) 00116 { 00117 rcs_ready_for_exit = 1; 00118 rcs_exit_sig = sig; 00119 } 00120 00121 void RCS_EXPORT 00122 rcs_exit (int code) 00123 { 00124 rcs_cleanup (code); 00125 #ifdef UNDER_CE 00126 ExitThread (code); 00127 #else 00128 #ifndef VXWORKS 00129 if (code == -1) 00130 { 00131 rcs_print_error ("\n Errors Reported!!!\n Press ^C to exit.\n"); 00132 signal (SIGINT, rcs_exit_signal_handler); 00133 int secs = 0; 00134 while (!rcs_ready_for_exit && secs < 600) 00135 { 00136 esleep (1.0); 00137 secs++; 00138 } 00139 } 00140 #endif 00141 exit (code); 00142 #endif 00143 }