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

Commiteb5e0d8

Browse files
committed
Split up process latch initialization for more-fail-soft behavior.
In the previous coding, new backend processes would attempt to create theirself-pipe during the OwnLatch call in InitProcess. However, pipe creationcould fail if the kernel is short of resources; and the system does notrecover gracefully from a FATAL error right there, since we have armed thedead-man switch for this process and not yet set up the on_shmem_exitcallback that would disarm it. The postmaster then forces an unnecessarydatabase-wide crash and restart, as reported by Sean Chittenden.There are various ways we could rearrange the code to fix this, but thesimplest and sanest seems to be to split out creation of the self-pipe intoa new function InitializeLatchSupport, which must be called from a placewhere failure is allowed. For most processes that gets called inInitProcess or InitAuxiliaryProcess, but processes that don't call eitherbut still use latches need their own calls.Back-patch to 9.1, which has only a part of the latch logic that 9.2 andHEAD have, but nonetheless includes this bug.
1 parentde31ea9 commiteb5e0d8

File tree

4 files changed

+59
-34
lines changed

4 files changed

+59
-34
lines changed

‎src/backend/port/unix_latch.c

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,50 @@ static volatile sig_atomic_t waiting = false;
4949
staticintselfpipe_readfd=-1;
5050
staticintselfpipe_writefd=-1;
5151

52-
/* private function prototypes */
53-
staticvoidinitSelfPipe(void);
54-
staticvoiddrainSelfPipe(void);
52+
/* Private function prototypes */
5553
staticvoidsendSelfPipeByte(void);
54+
staticvoiddrainSelfPipe(void);
55+
56+
57+
/*
58+
* Initialize the process-local latch infrastructure.
59+
*
60+
* This must be called once during startup of any process that can wait on
61+
* latches, before it issues any InitLatch() or OwnLatch() calls.
62+
*/
63+
void
64+
InitializeLatchSupport(void)
65+
{
66+
intpipefd[2];
67+
68+
Assert(selfpipe_readfd==-1);
69+
70+
/*
71+
* Set up the self-pipe that allows a signal handler to wake up the
72+
* select() in WaitLatch. Make the write-end non-blocking, so that
73+
* SetLatch won't block if the event has already been set many times
74+
* filling the kernel buffer. Make the read-end non-blocking too, so that
75+
* we can easily clear the pipe by reading until EAGAIN or EWOULDBLOCK.
76+
*/
77+
if (pipe(pipefd)<0)
78+
elog(FATAL,"pipe() failed: %m");
79+
if (fcntl(pipefd[0],F_SETFL,O_NONBLOCK)<0)
80+
elog(FATAL,"fcntl() failed on read-end of self-pipe: %m");
81+
if (fcntl(pipefd[1],F_SETFL,O_NONBLOCK)<0)
82+
elog(FATAL,"fcntl() failed on write-end of self-pipe: %m");
5683

84+
selfpipe_readfd=pipefd[0];
85+
selfpipe_writefd=pipefd[1];
86+
}
5787

5888
/*
5989
* Initialize a backend-local latch.
6090
*/
6191
void
6292
InitLatch(volatileLatch*latch)
6393
{
64-
/* Initialize the self-pipe if this is our first latch in the process */
65-
if (selfpipe_readfd==-1)
66-
initSelfPipe();
94+
/* Assert InitializeLatchSupport has been called in this process */
95+
Assert(selfpipe_readfd >=0);
6796

6897
latch->is_set= false;
6998
latch->owner_pid=MyProcPid;
@@ -105,11 +134,10 @@ InitSharedLatch(volatile Latch *latch)
105134
void
106135
OwnLatch(volatileLatch*latch)
107136
{
108-
Assert(latch->is_shared);
137+
/* Assert InitializeLatchSupport has been called in this process */
138+
Assert(selfpipe_readfd >=0);
109139

110-
/* Initialize the self-pipe if this is our first latch in this process */
111-
if (selfpipe_readfd==-1)
112-
initSelfPipe();
140+
Assert(latch->is_shared);
113141

114142
/* sanity check */
115143
if (latch->owner_pid!=0)
@@ -356,30 +384,6 @@ latch_sigusr1_handler(void)
356384
sendSelfPipeByte();
357385
}
358386

359-
/* initialize the self-pipe */
360-
staticvoid
361-
initSelfPipe(void)
362-
{
363-
intpipefd[2];
364-
365-
/*
366-
* Set up the self-pipe that allows a signal handler to wake up the
367-
* select() in WaitLatch. Make the write-end non-blocking, so that
368-
* SetLatch won't block if the event has already been set many times
369-
* filling the kernel buffer. Make the read-end non-blocking too, so that
370-
* we can easily clear the pipe by reading until EAGAIN or EWOULDBLOCK.
371-
*/
372-
if (pipe(pipefd)<0)
373-
elog(FATAL,"pipe() failed: %m");
374-
if (fcntl(pipefd[0],F_SETFL,O_NONBLOCK)<0)
375-
elog(FATAL,"fcntl() failed on read-end of self-pipe: %m");
376-
if (fcntl(pipefd[1],F_SETFL,O_NONBLOCK)<0)
377-
elog(FATAL,"fcntl() failed on write-end of self-pipe: %m");
378-
379-
selfpipe_readfd=pipefd[0];
380-
selfpipe_writefd=pipefd[1];
381-
}
382-
383387
/* Send one byte to the self-pipe, to wake up WaitLatch */
384388
staticvoid
385389
sendSelfPipeByte(void)

‎src/backend/port/win32_latch.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828
#include"storage/shmem.h"
2929

3030

31+
void
32+
InitializeLatchSupport(void)
33+
{
34+
/* currently, nothing to do here for Windows */
35+
}
36+
3137
void
3238
InitLatch(volatileLatch*latch)
3339
{

‎src/backend/storage/lmgr/proc.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,13 @@ InitProcess(void)
259259
if (MyProc!=NULL)
260260
elog(ERROR,"you already exist");
261261

262+
/*
263+
* Initialize process-local latch support. This could fail if the kernel
264+
* is low on resources, and if so we want to exit cleanly before acquiring
265+
* any shared-memory resources.
266+
*/
267+
InitializeLatchSupport();
268+
262269
/*
263270
* Try to get a proc struct from the free list. If this fails, we must be
264271
* out of PGPROC structures (not to mention semaphores).
@@ -424,6 +431,13 @@ InitAuxiliaryProcess(void)
424431
if (MyProc!=NULL)
425432
elog(ERROR,"you already exist");
426433

434+
/*
435+
* Initialize process-local latch support. This could fail if the kernel
436+
* is low on resources, and if so we want to exit cleanly before acquiring
437+
* any shared-memory resources.
438+
*/
439+
InitializeLatchSupport();
440+
427441
/*
428442
* We use the ProcStructLock to protect assignment and releasing of
429443
* AuxiliaryProcs entries.

‎src/include/storage/latch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ typedef struct
9494
/*
9595
* prototypes for functions in latch.c
9696
*/
97+
externvoidInitializeLatchSupport(void);
9798
externvoidInitLatch(volatileLatch*latch);
9899
externvoidInitSharedLatch(volatileLatch*latch);
99100
externvoidOwnLatch(volatileLatch*latch);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp