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
This commit is contained in:
parent
1d6fbc38d9
commit
422952ee78
|
@ -47,6 +47,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
#include "miscadmin.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -330,6 +331,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
|
||||||
shm_unlink(name);
|
shm_unlink(name);
|
||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we received a query cancel or termination signal, we will have
|
||||||
|
* EINTR set here. If the caller said that errors are OK here, check
|
||||||
|
* for interrupts immediately.
|
||||||
|
*/
|
||||||
|
if (errno == EINTR && elevel >= ERROR)
|
||||||
|
CHECK_FOR_INTERRUPTS();
|
||||||
|
|
||||||
ereport(elevel,
|
ereport(elevel,
|
||||||
(errcode_for_dynamic_shared_memory(),
|
(errcode_for_dynamic_shared_memory(),
|
||||||
errmsg("could not resize shared memory segment \"%s\" to %zu bytes: %m",
|
errmsg("could not resize shared memory segment \"%s\" to %zu bytes: %m",
|
||||||
|
@ -419,11 +428,15 @@ dsm_impl_posix_resize(int fd, off_t size)
|
||||||
#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
|
#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
{
|
{
|
||||||
/* We may get interrupted, if so just retry. */
|
/*
|
||||||
|
* We may get interrupted. If so, just retry unless there is an
|
||||||
|
* interrupt pending. This avoids the possibility of looping forever
|
||||||
|
* if another backend is repeatedly trying to interrupt us.
|
||||||
|
*/
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
rc = posix_fallocate(fd, 0, size);
|
rc = posix_fallocate(fd, 0, size);
|
||||||
} while (rc == EINTR);
|
} while (rc == EINTR && !(ProcDiePending || QueryCancelPending));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The caller expects errno to be set, but posix_fallocate() doesn't
|
* The caller expects errno to be set, but posix_fallocate() doesn't
|
||||||
|
|
Loading…
Reference in New Issue