1313 *
1414 *
1515 * IDENTIFICATION
16- * $PostgreSQL: pgsql/src/backend/storage/ipc/ipc.c,v 1.102 2009/01/01 17:23:47 momjian Exp $
16+ * $PostgreSQL: pgsql/src/backend/storage/ipc/ipc.c,v 1.103 2009/05/05 20:06:07 tgl Exp $
1717 *
1818 *-------------------------------------------------------------------------
1919 */
3737 */
3838bool proc_exit_inprogress = false;
3939
40+ /*
41+ * This flag tracks whether we've called atexit(2) in the current process
42+ * (or in the parent postmaster).
43+ */
44+ static bool atexit_callback_setup = false;
45+
46+ /* local functions */
47+ static void proc_exit_prepare (int code );
48+
4049
4150/* ----------------------------------------------------------------
4251 *exit() handling stuff
@@ -69,51 +78,21 @@ static inton_proc_exit_index,
6978 *
7079 *this function calls all the callbacks registered
7180 *for it (to free resources) and then calls exit.
81+ *
7282 *This should be the only function to call exit().
7383 *-cim 2/6/90
84+ *
85+ *Unfortunately, we can't really guarantee that add-on code
86+ *obeys the rule of not calling exit() directly. So, while
87+ *this is the preferred way out of the system, we also register
88+ *an atexit callback that will make sure cleanup happens.
7489 * ----------------------------------------------------------------
7590 */
7691void
7792proc_exit (int code )
7893{
79- /*
80- * Once we set this flag, we are committed to exit. Any ereport() will
81- * NOT send control back to the main loop, but right back here.
82- */
83- proc_exit_inprogress = true;
84-
85- /*
86- * Forget any pending cancel or die requests; we're doing our best to
87- * close up shop already. Note that the signal handlers will not set
88- * these flags again, now that proc_exit_inprogress is set.
89- */
90- InterruptPending = false;
91- ProcDiePending = false;
92- QueryCancelPending = false;
93- /* And let's just make *sure* we're not interrupted ... */
94- ImmediateInterruptOK = false;
95- InterruptHoldoffCount = 1 ;
96- CritSectionCount = 0 ;
97-
98- elog (DEBUG3 ,"proc_exit(%d)" ,code );
99-
100- /* do our shared memory exits first */
101- shmem_exit (code );
102-
103- /*
104- * call all the callbacks registered before calling exit().
105- *
106- * Note that since we decrement on_proc_exit_index each time, if a
107- * callback calls ereport(ERROR) or ereport(FATAL) then it won't be
108- * invoked again when control comes back here (nor will the
109- * previously-completed callbacks). So, an infinite loop should not be
110- * possible.
111- */
112- while (-- on_proc_exit_index >=0 )
113- (* on_proc_exit_list [on_proc_exit_index ].function ) (code ,
114- on_proc_exit_list [on_proc_exit_index ].arg );
115-
116- elog (DEBUG3 ,"exit(%d)" ,code );
94+ /* Clean up everything that must be cleaned up */
95+ proc_exit_prepare (code );
11796
11897#ifdef PROFILE_PID_DIR
11998{
@@ -134,7 +113,10 @@ proc_exit(int code)
134113 *
135114 * Note that we do this here instead of in an on_proc_exit() callback
136115 * because we want to ensure that this code executes last - we don't
137- * want to interfere with any other on_proc_exit() callback.
116+ * want to interfere with any other on_proc_exit() callback. For
117+ * the same reason, we do not include it in proc_exit_prepare ...
118+ * so if you are exiting in the "wrong way" you won't drop your profile
119+ * in a nice place.
138120 */
139121char gprofDirName [32 ];
140122
@@ -149,9 +131,59 @@ proc_exit(int code)
149131}
150132#endif
151133
134+ elog (DEBUG3 ,"exit(%d)" ,code );
135+
152136exit (code );
153137}
154138
139+ /*
140+ * Code shared between proc_exit and the atexit handler. Note that in
141+ * normal exit through proc_exit, this will actually be called twice ...
142+ * but the second call will have nothing to do.
143+ */
144+ static void
145+ proc_exit_prepare (int code )
146+ {
147+ /*
148+ * Once we set this flag, we are committed to exit. Any ereport() will
149+ * NOT send control back to the main loop, but right back here.
150+ */
151+ proc_exit_inprogress = true;
152+
153+ /*
154+ * Forget any pending cancel or die requests; we're doing our best to
155+ * close up shop already. Note that the signal handlers will not set
156+ * these flags again, now that proc_exit_inprogress is set.
157+ */
158+ InterruptPending = false;
159+ ProcDiePending = false;
160+ QueryCancelPending = false;
161+ /* And let's just make *sure* we're not interrupted ... */
162+ ImmediateInterruptOK = false;
163+ InterruptHoldoffCount = 1 ;
164+ CritSectionCount = 0 ;
165+
166+ /* do our shared memory exits first */
167+ shmem_exit (code );
168+
169+ elog (DEBUG3 ,"proc_exit(%d)" ,code );
170+
171+ /*
172+ * call all the registered callbacks.
173+ *
174+ * Note that since we decrement on_proc_exit_index each time, if a
175+ * callback calls ereport(ERROR) or ereport(FATAL) then it won't be
176+ * invoked again when control comes back here (nor will the
177+ * previously-completed callbacks). So, an infinite loop should not be
178+ * possible.
179+ */
180+ while (-- on_proc_exit_index >=0 )
181+ (* on_proc_exit_list [on_proc_exit_index ].function ) (code ,
182+ on_proc_exit_list [on_proc_exit_index ].arg );
183+
184+ on_proc_exit_index = 0 ;
185+ }
186+
155187/* ------------------
156188 * Run all of the on_shmem_exit routines --- but don't actually exit.
157189 * This is used by the postmaster to re-initialize shared memory and
@@ -176,6 +208,37 @@ shmem_exit(int code)
176208on_shmem_exit_index = 0 ;
177209}
178210
211+ /* ----------------------------------------------------------------
212+ *atexit_callback
213+ *
214+ *Backstop to ensure that direct calls of exit() don't mess us up.
215+ *
216+ * Somebody who was being really uncooperative could call _exit(),
217+ * but for that case we have a "dead man switch" that will make the
218+ * postmaster treat it as a crash --- see pmsignal.c.
219+ * ----------------------------------------------------------------
220+ */
221+ #ifdef HAVE_ATEXIT
222+
223+ static void
224+ atexit_callback (void )
225+ {
226+ /* Clean up everything that must be cleaned up */
227+ /* ... too bad we don't know the real exit code ... */
228+ proc_exit_prepare (-1 );
229+ }
230+
231+ #else /* assume we have on_exit instead */
232+
233+ static void
234+ atexit_callback (int exitstatus ,void * arg )
235+ {
236+ /* Clean up everything that must be cleaned up */
237+ proc_exit_prepare (exitstatus );
238+ }
239+
240+ #endif /* HAVE_ATEXIT */
241+
179242/* ----------------------------------------------------------------
180243 *on_proc_exit
181244 *
@@ -195,6 +258,16 @@ on_proc_exit(pg_on_exit_callback function, Datum arg)
195258on_proc_exit_list [on_proc_exit_index ].arg = arg ;
196259
197260++ on_proc_exit_index ;
261+
262+ if (!atexit_callback_setup )
263+ {
264+ #ifdef HAVE_ATEXIT
265+ atexit (atexit_callback );
266+ #else
267+ on_exit (atexit_callback ,NULL );
268+ #endif
269+ atexit_callback_setup = true;
270+ }
198271}
199272
200273/* ----------------------------------------------------------------
@@ -216,6 +289,16 @@ on_shmem_exit(pg_on_exit_callback function, Datum arg)
216289on_shmem_exit_list [on_shmem_exit_index ].arg = arg ;
217290
218291++ on_shmem_exit_index ;
292+
293+ if (!atexit_callback_setup )
294+ {
295+ #ifdef HAVE_ATEXIT
296+ atexit (atexit_callback );
297+ #else
298+ on_exit (atexit_callback ,NULL );
299+ #endif
300+ atexit_callback_setup = true;
301+ }
219302}
220303
221304/* ----------------------------------------------------------------