1- /*-------------------------------------------------------------------------
1+ /*-------------------------------------------------------------------------
22 *
33 * ipc.c
44 * POSTGRES inter-process communication definitions.
77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.42 1999/11/06 19:46:57 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipc.c,v 1.43 1999/11/22 02:06:31 tgl Exp $
1111 *
1212 * NOTES
1313 *
2828#include <sys/file.h>
2929#include <errno.h>
3030
31-
3231#include "postgres.h"
32+
3333#include "storage/ipc.h"
3434#include "storage/s_lock.h"
3535/* In Ultrix, sem.h and shm.h must be included AFTER ipc.h */
4343#include <sys/ipc.h>
4444#endif
4545
46+ /*
47+ * This flag is set during proc_exit() to change elog()'s behavior,
48+ * so that an elog() from an on_proc_exit routine cannot get us out
49+ * of the exit procedure. We do NOT want to go back to the idle loop...
50+ */
51+ bool proc_exit_inprogress = false;
52+
4653static int UsePrivateMemory = 0 ;
4754
4855static void IpcMemoryDetach (int status ,char * shmaddr );
@@ -70,7 +77,8 @@ typedef struct _PrivateMemStruct
7077char * memptr ;
7178}PrivateMem ;
7279
73- PrivateMem IpcPrivateMem [16 ];
80+ static PrivateMem IpcPrivateMem [16 ];
81+
7482
7583static int
7684PrivateMemoryCreate (IpcMemoryKey memKey ,
@@ -105,45 +113,34 @@ PrivateMemoryAttach(IpcMemoryId memid)
105113 *-cim 2/6/90
106114 * ----------------------------------------------------------------
107115 */
108- static int proc_exit_inprogress = 0 ;
109-
110116void
111117proc_exit (int code )
112118{
113- int i ;
114-
115- TPRINTF (TRACE_VERBOSE ,"proc_exit(%d) [#%d]" ,code ,proc_exit_inprogress );
116-
117119/*
118- *If proc_exit is called too many times something bad is happening, so
119- *exit immediately. This is crafted in two if's for a reason .
120+ *Once we set this flag, we are committed to exit. Any elog() will
121+ *NOT send control back to the main loop, but right back here .
120122 */
123+ proc_exit_inprogress = true;
121124
122- if (++ proc_exit_inprogress == 9 )
123- elog (ERROR ,"infinite recursion in proc_exit" );
124- if (proc_exit_inprogress >=9 )
125- gotoexit ;
126-
127- /* ----------------
128- *if proc_exit_inprocess > 1, then it means that we
129- *are being invoked from within an on_exit() handler
130- *and so we return immediately to avoid recursion.
131- * ----------------
132- */
133- if (proc_exit_inprogress > 1 )
134- return ;
125+ TPRINTF (TRACE_VERBOSE ,"proc_exit(%d)" ,code );
135126
136127/* do our shared memory exits first */
137128shmem_exit (code );
138129
139130/* ----------------
140131 *call all the callbacks registered before calling exit().
132+ *
133+ *Note that since we decrement on_proc_exit_index each time,
134+ *if a callback calls elog(ERROR) or elog(FATAL) then it won't
135+ *be invoked again when control comes back here (nor will the
136+ *previously-completed callbacks). So, an infinite loop
137+ *should not be possible.
141138 * ----------------
142139 */
143- for (i = on_proc_exit_index - 1 ;i >=0 ;-- i )
144- (* on_proc_exit_list [i ].function ) (code ,on_proc_exit_list [i ].arg );
140+ while (-- on_proc_exit_index >=0 )
141+ (* on_proc_exit_list [on_proc_exit_index ].function ) (code ,
142+ on_proc_exit_list [on_proc_exit_index ].arg );
145143
146- exit :
147144TPRINTF (TRACE_VERBOSE ,"exit(%d)" ,code );
148145exit (code );
149146}
@@ -154,44 +151,23 @@ proc_exit(int code)
154151 * semaphores after a backend dies horribly
155152 * ------------------
156153 */
157- static int shmem_exit_inprogress = 0 ;
158-
159154void
160155shmem_exit (int code )
161156{
162- int i ;
163-
164- TPRINTF (TRACE_VERBOSE ,"shmem_exit(%d) [#%d]" ,
165- code ,shmem_exit_inprogress );
166-
167- /*
168- * If shmem_exit is called too many times something bad is happenig,
169- * so exit immediately.
170- */
171- if (shmem_exit_inprogress > 9 )
172- {
173- elog (ERROR ,"infinite recursion in shmem_exit" );
174- exit (-1 );
175- }
176-
177- /* ----------------
178- *if shmem_exit_inprocess is true, then it means that we
179- *are being invoked from within an on_exit() handler
180- *and so we return immediately to avoid recursion.
181- * ----------------
182- */
183- if (shmem_exit_inprogress ++ )
184- return ;
157+ TPRINTF (TRACE_VERBOSE ,"shmem_exit(%d)" ,code );
185158
186159/* ----------------
187- *call all the callbacks registered before calling exit().
160+ *call all the registered callbacks.
161+ *
162+ *As with proc_exit(), we remove each callback from the list
163+ *before calling it, to avoid infinite loop in case of error.
188164 * ----------------
189165 */
190- for (i = on_shmem_exit_index - 1 ;i >=0 ;-- i )
191- (* on_shmem_exit_list [i ].function ) (code ,on_shmem_exit_list [i ].arg );
166+ while (-- on_shmem_exit_index >=0 )
167+ (* on_shmem_exit_list [on_shmem_exit_index ].function ) (code ,
168+ on_shmem_exit_list [on_shmem_exit_index ].arg );
192169
193170on_shmem_exit_index = 0 ;
194- shmem_exit_inprogress = 0 ;
195171}
196172
197173/* ----------------------------------------------------------------
@@ -202,7 +178,7 @@ shmem_exit(int code)
202178 * ----------------------------------------------------------------
203179 */
204180int
205- on_proc_exit (void (* function ) (),caddr_t arg )
181+ on_proc_exit (void (* function ) (),caddr_t arg )
206182{
207183if (on_proc_exit_index >=MAX_ON_EXITS )
208184return -1 ;
223199 * ----------------------------------------------------------------
224200 */
225201int
226- on_shmem_exit (void (* function ) (),caddr_t arg )
202+ on_shmem_exit (void (* function ) (),caddr_t arg )
227203{
228204if (on_shmem_exit_index >=MAX_ON_EXITS )
229205return -1 ;