Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f547035

Browse files
committed
Allow DSM allocation to be interrupted.
Chris Travers reported that the startup process can repeatedly try to cancel a backend that is in a posix_fallocate()/EINTR loop and cause it to loop forever. Teach the retry loop to give up if an interrupt is pending. Don't actually check for interrupts in that loop though, because a non-local exit would skip some clean-up code in the caller. Back-patch to 9.4 where DSM was added (and posix_fallocate() was later back-patched). Author: Chris Travers Reviewed-by: Ildar Musin, Murat Kabilov, Oleksii Kliukin Tested-by: Oleksii Kliukin Discussion: https://postgr.es/m/CAN-RpxB-oeZve_J3SM_6%3DHXPmvEG%3DHX%2B9V9pi8g2YR7YW0rBBg%40mail.gmail.com
1 parent 2a97a0a commit f547035

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

src/backend/storage/ipc/dsm_impl.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
*/
4848

4949
#include "postgres.h"
50+
#include "miscadmin.h"
5051

5152
#include <fcntl.h>
5253
#include <string.h>
@@ -332,6 +333,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
332333
shm_unlink(name);
333334
errno = save_errno;
334335

336+
/*
337+
* If we received a query cancel or termination signal, we will have
338+
* EINTR set here. If the caller said that errors are OK here, check
339+
* for interrupts immediately.
340+
*/
341+
if (errno == EINTR && elevel >= ERROR)
342+
CHECK_FOR_INTERRUPTS();
343+
335344
ereport(elevel,
336345
(errcode_for_dynamic_shared_memory(),
337346
errmsg("could not resize shared memory segment \"%s\" to %zu bytes: %m",
@@ -421,11 +430,15 @@ dsm_impl_posix_resize(int fd, off_t size)
421430
#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
422431
if (rc == 0)
423432
{
424-
/* We may get interrupted, if so just retry. */
433+
/*
434+
* We may get interrupted. If so, just retry unless there is an
435+
* interrupt pending. This avoids the possibility of looping forever
436+
* if another backend is repeatedly trying to interrupt us.
437+
*/
425438
do
426439
{
427440
rc = posix_fallocate(fd, 0, size);
428-
} while (rc == EINTR);
441+
} while (rc == EINTR && !(ProcDiePending || QueryCancelPending));
429442

430443
/*
431444
* The caller expects errno to be set, but posix_fallocate() doesn't

0 commit comments

Comments
 (0)