1ggRegisterCleanup(3)                  GGI                 ggRegisterCleanup(3)
2
3
4

NAME

6       ggRegisterCleanup,  ggUnregisterCleanup,  ggCleanupForceExit  : Cleanup
7       callback facilities
8

SYNOPSIS

10       #include <ggi/gg.h>
11
12       typedef void (ggcleanup_func)(void *);
13
14       int ggRegisterCleanup(ggcleanup_func *func, void *arg);
15
16       int ggUnregisterCleanup(ggcleanup_func *func, void *arg);
17
18       void ggCleanupForceExit(void);
19
20

DESCRIPTION

22       ggRegisterCleanup registers a callback function ("handler") to be  exe‐
23       cuted  when any abnormal or unexpected program termination is imminent.
24       The function will be called with its argument.
25
26       ggUnregisterCleanup  cancels  a  callback  installed  with  ggRegister‐
27       Cleanup.   If  more  than  one  exactly  identical  callbacks have been
28       installed, the most recently installed one is canceled.
29
30       ggCleanupForceExit may only be called from within a LibGG cleanup  han‐
31       dler.   Once  ggCleanupForceExit is called, _exit(2) will be explicitly
32       called  after  all  registered  cleanup  callbacks  have  completed  by
33       ggExit(3),  assuming there is no error that prevents them from complet‐
34       ing.  It is not possible to cancel such a  request  once  it  has  been
35       made.
36
37       Cleanup  functions  are executed in LIFO order.  They are guaranteed to
38       only be executed once during program termination or during ggExit(3).
39
40       These functions are for emergency use only, and should not be used as a
41       substitute to proper memory deallocation routines.  They should only be
42       used to restore system state that would  otherwise  be  left  corrupted
43       after an abnormal program termination, for example, a video-card timing
44       mode or tty mode.  When normal termination occurs,  ggUnregisterCleanup
45       should  be  called  to  systematically  remove  the emergency callbacks
46       before ggExit(3) or exit(3) are called.
47
48       Callback functions registered with ggRegisterCleanup should  not  them‐
49       selves  invoke  (or invoke any subroutines that may in turn invoke) any
50       of  the  LibGG  locking  functions  ggLockCreate(3),  ggLockDestroy(3),
51       ggLock(3),  ggUnlock(3), or ggTryLock(3).  However, since callbacks are
52       only invoked during emergencies, they should be ignoring locks in  gen‐
53       eral.  If a callback function may be used by anything other than LibGG,
54       it must also be reentrant.  Callback functions can come at any time, so
55       write  them with this in mind -- make them minimal and tolerant of con‐
56       current access to global read/write data and avoid accessing such  data
57       in the first place if it is not absolutely necessary.
58
59       The callback functions may be called by a normal call to ggExit(3).  As
60       such, it is considered best  practice  to  use  ggUnregisterCleanup  to
61       remove  cleanups when gracefully deinitializing LibGG or a library that
62       uses LibGG, before ggExit(3) is called.
63
64       ggRegisterCleanup and ggUnregisterCleanup are threadsafe, however, they
65       are  not  safe  to call from a thread that may be canceled during their
66       execution, and they are not guaranteed to be safe to  call  from  LibGG
67       tasks  or any other special context such as a signal handler or a asyn‐
68       cronous procedure call.  Above all  they  should  not  be  called  from
69       inside a LibGG cleanup handler.
70

RETURN VALUE

72       ggRegisterCleanup  returns  GGI_OK  on  success,  or one of these error
73       codes:
74
75       ·   GGI_EUNKNOWN;
76
77       ·   GGI_ENOMEM;
78
79       ·   GGI_EBUSY.
80
81       ggUnregisterCleanup returns GGI_OK on success, or one  of  these  error
82       codes:
83
84       ·   GGI_EBUSY;
85
86       ·   GGI_ENOTALLOC;
87
88       ·   GGI_ENOMEM.
89

INTERACTION WITH UNIX SIGNALS

91       On UNIX systems the LibGG cleanup facilities install signal handlers as
92       per signal(3) or sigaction(2).  It is advisible to  use  LibGG  cleanup
93       handlers instead of UNIX signals for the purpose of catching fatal sig‐
94       nals because they are implemented portably, however, this is not always
95       an  option  when mixing LibGG with other libraries.  When LibGG must be
96       used with other code that also installs signal  handlers,  consult  the
97       following section.
98
99       LibGG  installs  signal  handlers  for those signals which are normally
100       fatal to the program.  The  exact  set  of  functions  that  is  caught
101       depends  on the software platform.  LibGG installs signal handlers when
102       the first LibGG cleanup handler is installed.  These  may  in  fact  be
103       installed  in ggInit(3) as LibGG may use cleanups internally.  The only
104       way to be sure that the LibGG  signal  handlers  are  installed  is  to
105       install a cleanup after ggInit(3).
106
107       By  setting any signal handler to SIG_IGN before calling ggInit(3), the
108       application can force LibGG to ignore the signal, so that cleanups  are
109       not run when that particular signal is received.  LibGG will also over‐
110       load any application signal handlers for fatal signals that are present
111       when  it installs a signal handler.  Overloaded signal handlers will be
112       run before cleanups are run when the  signal  occurs.   The  overloaded
113       signal handler is not guaranteed to be called exactly as it would be by
114       the main application, for example, support for the  long  form  of  the
115       signal handler prototype available through sigaction(2) on some systems
116       is not yet implemented, though it may be in the future.
117
118       If the system uses the tradition (broken) UNIX  signal  behavior  where
119       signal  handlers  are  set to SIG_DFL to 'block' additional occurances,
120       this may result in rare instances where signal handlers are  reentered.
121       Thus  the  signal  handler  for  a given signal may call the overloaded
122       cleanup multiple times before cleanup functions are called.  This  will
123       also  apply  to signal handlers that manipulate the signal mask on more
124       advanced sigaction(2) based systems.
125
126       Signals that arrive after that signal which triggers the cleanup  call‐
127       backs may have their handlers run before or during the execution of the
128       cleanups.
129
130       After ggInit(3) and ggRegisterCleanup are  called,  individual  signals
131       may  be  overridden  by  application-specific signal handlers or set to
132       SIG_IGN or SIG_DFL.  This will prevent LibGG cleanups  from  being  run
133       when  the signal occurs.  Within limits, it is also acceptable to over‐
134       load the LibGG signal handler.  However it is not  acceptable  to  call
135       the LibGG signal handler with signum equal to any signal on which LibGG
136       did not initially install  the  handler  function,  and  deinitializing
137       LibGG  while  overloading its signal handler may cause undefined bahav‐
138       ior.
139

SHORT TUTORIAL ON WRITING DECENT SIGNAL HANDLERS

141       LibGG attempts to be tolerant of badly  written  signal  handlers,  but
142       consistant,  correct behavior can only be guaranteed if signal handlers
143       are written within the following guidelines.  First, a  signal  handler
144       must  be  written  using  sigaction  if  sigaction is available, or the
145       results may not be perfect.  If sigaction is not available, the  proper
146       code for a simple, overloadable signal handler is such:
147
148       lasthandler = signal(signum, SIG_DFL));
149       /* do stuff */
150       if (lasthandler == SIG_DFL) signal(signum, current_handler);
151       else signal(signum, lasthandler);
152
153       This  code  looks  circumlocuitous but each part is important for main‐
154       taining overloadability in a  portable  fashion.   The  signal  handler
155       should not reinstall itself unless it detects original UNIX signals are
156       in effect by detecting the automatically installed SIG_DFL, or else  it
157       might   get  called  directly,  skipping  the  parent  signal  handler.
158       Installing SIG_DFL temporarily should be harmless to BSD style  signals
159       because  the OS is required to block stacked signals through some other
160       mechanism until the signal handler returns.
161
162       In order to overload a signal handler, again  still  dealing  with  the
163       situation where sigaction is not available, the above code can be modi‐
164       fied as such:
165
166       lasthandler = signal(signum, SIG_DFL);
167       /* do stuff */
168       if (had_oldhandler) {
169            signal(signum, lasthandler);
170            oldhandler(signum);
171       }
172       if (lasthandler == SIG_DFL) signal(signum, current_handler);
173       else signal(signum, lasthandler);
174
175       This is not perfect because it may allow lasthandler  to  be  reentered
176       when  used  on  a  system with the original UNIX behavior, in the short
177       period between when  lasthandler  is  reinstalled  and  the  oldhandler
178       installs  SIG_DFL.   However,  if  the  handlers are all reentrant this
179       should work fine.  In the BSD behavior, this again is harmless  because
180       other OS mechanisms prevent reentry.
181
182       Systems  without  sigaction  are pretty cretinous and rarer these days,
183       however.  When sigaction(2) is available we can assume that signal han‐
184       dlers  do  not  need  to  reinstall themselves as per the original UNIX
185       SIG_DFL behavior.  As such no special consideration is needed to  write
186       a  proper overloading/overloadable handler, however, in order to assure
187       that cleanup functions are only run once even in multithreaded,  multi‐
188       processor environments, LibGG may need to temporarily overload a signal
189       handler which has overloaded LibGG's signal handler with a dummy  pass-
190       through  handler, and as of this writing LibGG's behavior when the sig‐
191       nal mask is altered is not yet specified and should be considered unde‐
192       fined.
193
194       Measures are taken within LibGG to limit the impact of interaction with
195       badly written signal handlers that reinstall their own handler when  it
196       is not needed or desired, however it is recommended that libraries that
197       use such handlers be updated to use better code when compiled  on  more
198       modern systems.
199
200       One last note on stacking signal handlers: When writing for an environ‐
201       ment where different libraries may overload signals, all libraries must
202       prevent  loops  from  forming.   It  is not sufficient that they simply
203       check that they  never  overload  their  own  signal  handler,  because
204       another  library  may have overloaded it already, and thus you may have
205       handler A calling handler B calling handler A which then calls  handler
206       B  again.   Libraries  must keep track of whether their signal handlers
207       are installed or not through other means.
208

FALLBACK MODE

210       LibGG expects some sort of signal-like system  to  be  present  in  the
211       environment,  otherwise  there  is  no  way  to  implement the behavior
212       described above.  When LibGG is compiled on a system that has  no  such
213       support,  a  fallback mode is invoked where cleanup handlers are regis‐
214       tered with the atexit(3) facility, or anything it may have that is like
215       atexit(3).   It may not be possible to unregister cleanups supported in
216       such a way, and they will always run at normal program exit, even after
217       LibGG  is exited.  There is no way for them to run during abnormal ter‐
218       mination.
219
220
221
222libgg-1.0.x                       2005-08-26              ggRegisterCleanup(3)
Impressum