1 /*
2 * $LynxId: LYexit.c,v 1.38 2020/02/25 10:14:48 tom Exp $
3 *
4 * Copyright (c) 1994, University of Kansas, All Rights Reserved
5 * (most of this file was rewritten in 1996 and 2004).
6 */
7 #include <HTUtils.h>
8 #include <LYexit.h>
9 #include <HTAlert.h>
10 #ifndef VMS
11 #include <LYGlobalDefs.h>
12 #include <LYUtils.h>
13 #include <LYSignal.h>
14 #include <LYMainLoop.h>
15 #endif /* !VMS */
16 #include <LYStrings.h>
17 #include <LYClean.h>
18
19 /*
20 * Flag for outofmem macro. - FM
21 */
22 BOOL LYOutOfMemory = FALSE;
23
24 /*
25 * Stack of functions to call upon exit.
26 */
27 static void (*callstack[ATEXITSIZE]) (void);
28 static int topOfStack = 0;
29
30 /*
31 * Capture "atexit()" calls for our own accounting.
32 */
LYatexit(void (* function)(void))33 int LYatexit(void (*function) (void))
34 {
35 int result = 0;
36
37 if (topOfStack >= ATEXITSIZE) {
38 CTRACE((tfp, "(LY)atexit: Too many functions, ignoring one!\n"));
39 result = -1;
40 } else {
41 int n;
42 BOOLEAN found = FALSE;
43
44 for (n = 0; n < topOfStack; ++n) {
45 if (callstack[n] == function) {
46 found = TRUE;
47 break;
48 }
49 }
50 if (!found) {
51 callstack[topOfStack++] = function;
52 }
53 }
54 return result;
55 }
56
57 /*
58 * Purpose: Call the functions registered with LYatexit
59 * Arguments: void
60 * Return Value: void
61 * Remarks/Portability/Dependencies/Restrictions:
62 * Revision History:
63 * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe
64 */
LYCompleteExit(void)65 static void LYCompleteExit(void)
66 {
67 /*
68 * Just loop through registered functions. This is reentrant if more exits
69 * occur in the registered functions.
70 */
71 while (--topOfStack >= 0) {
72 callstack[topOfStack] ();
73 }
74 }
75
76 /*
77 * Purpose: Terminates program, reports memory not freed.
78 * Arguments: status Exit code.
79 * Return Value: void
80 * Remarks/Portability/Dependencies/Restrictions:
81 * Function calls stdlib.h exit
82 * Revision History:
83 * 06-15-94 created Lynx 2-3-1 Garrett Arch Blythe
84 */
LYexit(int status)85 void LYexit(int status)
86 {
87 #ifndef VMS /* On VMS, the VMSexit() handler does these. - FM */
88 #ifdef _WINDOWS
89 DeleteCriticalSection(&critSec_READ);
90
91 WSACleanup();
92 #endif
93 if (LYOutOfMemory == TRUE) {
94 /*
95 * Ignore further interrupts. - FM
96 */
97 #ifndef NOSIGHUP
98 (void) signal(SIGHUP, SIG_IGN);
99 #endif /* NOSIGHUP */
100 (void) signal(SIGTERM, SIG_IGN);
101 (void) signal(SIGINT, SIG_IGN);
102 #ifndef __linux__
103 #ifdef SIGBUS
104 (void) signal(SIGBUS, SIG_IGN);
105 #endif /* SIGBUS */
106 #endif /* !__linux__ */
107 (void) signal(SIGSEGV, SIG_IGN);
108 (void) signal(SIGILL, SIG_IGN);
109
110 /*
111 * Flush all messages. - FM
112 */
113 fflush(stderr);
114 fflush(stdout);
115
116 /*
117 * Deal with curses, if on, and clean up. - FM
118 */
119 if (LYCursesON) {
120 LYSleepAlert();
121 }
122 cleanup_sig(0);
123 #ifndef __linux__
124 #ifdef SIGBUS
125 signal(SIGBUS, SIG_DFL);
126 #endif /* SIGBUS */
127 #endif /* !__linux__ */
128 signal(SIGSEGV, SIG_DFL);
129 signal(SIGILL, SIG_DFL);
130 }
131 #endif /* !VMS */
132
133 /*
134 * Close syslog before doing atexit-cleanup, since it may use a string
135 * that would be freed there.
136 */
137 #ifdef SYSLOG_REQUESTED_URLS
138 LYCloselog();
139 #endif
140
141 /*
142 * Do functions registered with LYatexit. - GAB
143 */
144 LYCompleteExit();
145
146 LYCloseCmdLogfile();
147
148 #ifdef exit
149 /* Make sure we use stdlib exit and not LYexit. - GAB
150 */
151 #undef exit
152 #endif /* exit */
153
154 cleanup_files(); /* if someone starts with LYNXfoo: page */
155 #ifndef VMS /* On VMS, the VMSexit() handler does these. - FM */
156 fflush(stderr);
157 if (LYOutOfMemory == TRUE) {
158 LYOutOfMemory = FALSE;
159 printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
160 fflush(stdout);
161 }
162 LYCloseTracelog();
163 #endif /* !VMS */
164 show_alloc();
165
166 #if defined(NCURSES_VERSION) && defined(LY_FIND_LEAKS)
167 #if defined(HAVE_CURSES_EXIT)
168 curses_exit(status);
169 #elif defined(HAVE__NC_FREE_AND_EXIT)
170 _nc_free_and_exit(status);
171 #elif defined(HAVE__NC_FREEALL)
172 _nc_freeall();
173 #endif
174 #endif /* NCURSES_VERSION */
175
176 exit(status);
177 }
178
outofmem(const char * fname,const char * func)179 void outofmem(const char *fname,
180 const char *func)
181 {
182 fprintf(stderr, "\n\n\n%s %s: %s\n", fname, func, MEMORY_EXHAUSTED_ABORTING);
183 LYOutOfMemory = TRUE;
184 LYexit(-1);
185 }
186