Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit249a899

Browse files
committed
Install an atexit(2) callback that ensures that proc_exit's cleanup processing
will still be performed if something in a backend process calls exit()directly, instead of going through proc_exit() as we prefer. This is a secondresponse to the issue that we might load third-party code that doesn't know itshould not call exit(). Such a call will now cause a reasonably gracefulbackend shutdown, if possible. (Of course, if the reason for the exit() callis out-of-memory or some such, we might not be able to recover, but at leastwe will try.)
1 parent969d7cd commit249a899

File tree

1 file changed

+123
-40
lines changed
  • src/backend/storage/ipc

1 file changed

+123
-40
lines changed

‎src/backend/storage/ipc/ipc.c

Lines changed: 123 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
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
*/
@@ -37,6 +37,15 @@
3737
*/
3838
boolproc_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+
staticboolatexit_callback_setup= false;
45+
46+
/* local functions */
47+
staticvoidproc_exit_prepare(intcode);
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
*/
7691
void
7792
proc_exit(intcode)
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
#ifdefPROFILE_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
*/
139121
chargprofDirName[32];
140122

@@ -149,9 +131,59 @@ proc_exit(int code)
149131
}
150132
#endif
151133

134+
elog(DEBUG3,"exit(%d)",code);
135+
152136
exit(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+
staticvoid
145+
proc_exit_prepare(intcode)
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)
176208
on_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+
#ifdefHAVE_ATEXIT
222+
223+
staticvoid
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+
staticvoid
234+
atexit_callback(intexitstatus,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)
195258
on_proc_exit_list[on_proc_exit_index].arg=arg;
196259

197260
++on_proc_exit_index;
261+
262+
if (!atexit_callback_setup)
263+
{
264+
#ifdefHAVE_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)
216289
on_shmem_exit_list[on_shmem_exit_index].arg=arg;
217290

218291
++on_shmem_exit_index;
292+
293+
if (!atexit_callback_setup)
294+
{
295+
#ifdefHAVE_ATEXIT
296+
atexit(atexit_callback);
297+
#else
298+
on_exit(atexit_callback,NULL);
299+
#endif
300+
atexit_callback_setup= true;
301+
}
219302
}
220303

221304
/* ----------------------------------------------------------------

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp