aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2018-09-18 22:56:36 +1200
committerThomas Munro <tmunro@postgresql.org>2018-09-18 23:03:54 +1200
commit63efab4ca139ab18095b8e095d5708d5566fc9e2 (patch)
tree8fe28b28953b90d9a38162a7e3581f6762bf24de /src/backend
parent3d65e406d1ea82060ad13a7bc41178ed22c599d1 (diff)
downloadpostgresql-63efab4ca139ab18095b8e095d5708d5566fc9e2.tar.gz
postgresql-63efab4ca139ab18095b8e095d5708d5566fc9e2.zip
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
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/storage/ipc/dsm_impl.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/backend/storage/ipc/dsm_impl.c b/src/backend/storage/ipc/dsm_impl.c
index c6382ec031b..b79701d8375 100644
--- a/src/backend/storage/ipc/dsm_impl.c
+++ b/src/backend/storage/ipc/dsm_impl.c
@@ -47,6 +47,7 @@
*/
#include "postgres.h"
+#include "miscadmin.h"
#include <fcntl.h>
#include <unistd.h>
@@ -333,6 +334,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size,
shm_unlink(name);
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,
(errcode_for_dynamic_shared_memory(),
errmsg("could not resize shared memory segment \"%s\" to %zu bytes: %m",
@@ -422,11 +431,15 @@ dsm_impl_posix_resize(int fd, off_t size)
#if defined(HAVE_POSIX_FALLOCATE) && defined(__linux__)
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
{
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