/ src / libnml / rcs / rcs_exit.cc
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  }