Skip to content

Commit 3a2acfe

Browse files
author
Rafa de la Torre
authored
Merge pull request #2 from CartoDB/plpy-interrupt
Plpy interrupt
2 parents 496791c + 12b89e0 commit 3a2acfe

File tree

2 files changed

+53
-24
lines changed

2 files changed

+53
-24
lines changed

debian/changelog

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
postgresql-9.5 (9.5.2-3cdb3) precise; urgency=medium
2+
3+
* Improved patch for interruptible PLPython functions
4+
5+
-- Rafa de la Torre <[email protected]> Tue, 23 May 2017 18:48:02 +0200
6+
17
postgresql-9.5 (9.5.2-3cdb2) precise; urgency=low
28

39
* Release 9.5.2-3cdb2

debian/patches/92-plpython-interrupt.patch

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,89 @@
1-
From c7f7c818d90b8f94103b218732ba749db6812ea9 Mon Sep 17 00:00:00 2001
2-
From: Mario de Frutos <[email protected]>
3-
Date: Fri, 14 Oct 2016 18:44:31 +0200
4-
Subject: [PATCH] Handler to manage interrupts for python code inside PLPython
1+
commit b319ceef00d3a9cfd5b7a4bd0bc9a892ca18149b
2+
Author: Javier Goizueta <[email protected]>
3+
Date: Fri May 5 12:27:15 2017 +0200
54

6-
---
7-
src/pl/plpython/plpy_main.c | 35 +++++++++++++++++++++++++++++++++++
8-
1 file changed, 35 insertions(+)
5+
Make execution of plpython interruptible
6+
7+
The plpy module hooks into the signal handling mechanism to insert python exceptions when a SIGINT occurs.
98

109
diff --git a/src/pl/plpython/plpy_main.c b/src/pl/plpython/plpy_main.c
11-
index 5dd86c6..b2632cd 100644
10+
index 5dd86c6..9f53453 100644
1211
--- a/src/pl/plpython/plpy_main.c
1312
+++ b/src/pl/plpython/plpy_main.c
14-
@@ -74,6 +74,10 @@ PyObject *PLy_interp_globals = NULL;
13+
@@ -74,6 +74,9 @@ PyObject *PLy_interp_globals = NULL;
1514
/* this doesn't need to be global; use PLy_current_execution_context() */
1615
static PLyExecutionContext *PLy_execution_contexts = NULL;
1716

1817
+/* postgres backend handler for interruption */
1918
+static pqsigfunc coreIntHandler = 0;
2019
+static void PLy_handle_interrupt(int sig);
21-
+
2220

2321
void
2422
_PG_init(void)
25-
@@ -81,6 +85,9 @@ _PG_init(void)
23+
@@ -81,6 +84,9 @@ _PG_init(void)
2624
int **bitmask_ptr;
2725
const int **version_ptr;
2826

29-
+ // Catch and process signals
30-
+ coreIntHandler = pqsignal(SIGINT, PLy_handle_interrupt);
27+
+ /* Catch and process SIGINT signals */
28+
+ coreIntHandler = pqsignal(SIGINT, PLy_handle_interrupt);
3129
+
3230
/*
3331
* Set up a shared bitmask variable telling which Python version(s) are
3432
* loaded into this process's address space. If there's more than one, we
35-
@@ -454,3 +461,31 @@ PLy_pop_execution_context(void)
33+
@@ -425,6 +431,9 @@ PLy_current_execution_context(void)
34+
return PLy_execution_contexts;
35+
}
36+
37+
+/* Indicate tha a python interruption is pending */
38+
+static int PLy_pending_interrupt = 0;
39+
+
40+
static PLyExecutionContext *
41+
PLy_push_execution_context(void)
42+
{
43+
@@ -451,6 +460,46 @@ PLy_pop_execution_context(void)
44+
45+
PLy_execution_contexts = context->next;
46+
47+
+ if (PLy_execution_contexts == NULL) {
48+
+ // Clear pending interrupts when top level context exits
49+
+ PLy_pending_interrupt = 0;
50+
+ }
51+
+
3652
MemoryContextDelete(context->scratch_ctx);
3753
PLy_free(context);
3854
}
3955
+
40-
+void _PG_fini(void);
4156
+void
4257
+_PG_fini(void)
4358
+{
44-
+ if (coreIntHandler) {
45-
+ pqsignal(SIGINT, coreIntHandler);
46-
+ }
59+
+ // Restore previous SIGINT handler
60+
+ pqsignal(SIGINT, coreIntHandler);
4761
+}
4862
+
4963
+static int
5064
+PLy_python_interruption_handler()
5165
+{
66+
+ if (!PLy_pending_interrupt) {
67+
+ return 0;
68+
+ }
69+
+
70+
+ PLy_pending_interrupt = 0;
5271
+ PyErr_SetString(PyExc_RuntimeError, "Execution of function interrupted by signal");
53-
+ return 0;
72+
+ return -1;
5473
+}
5574
+
5675
+static void
5776
+PLy_handle_interrupt(int sig)
5877
+{
59-
+ // custom interruption
60-
+ Py_AddPendingCall(PLy_python_interruption_handler, NULL);
61-
+
62-
+ if (coreIntHandler) {
78+
+ if (PLy_execution_contexts != NULL && !PLy_pending_interrupt) {
79+
+ PLy_pending_interrupt = 1;
80+
+ Py_AddPendingCall(PLy_python_interruption_handler, NULL);
81+
+ }
82+
+ // Fallback to execute prior handlers
83+
+ if (coreIntHandler != SIG_DFL && coreIntHandler != SIG_IGN) {
84+
+ // There's a catch here: if the prior handler was SIG_DFL we have no easy way
85+
+ // of invoking it here;
86+
+ // As that's an unlikely situation we'll just treat SIG_DFL as SIG_IGN.
6387
+ (*coreIntHandler)(sig);
6488
+ }
6589
+}
66-
+

0 commit comments

Comments
 (0)