|
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 |
5 | 4 |
|
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. |
9 | 8 |
|
10 | 9 | 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 |
12 | 11 | --- a/src/pl/plpython/plpy_main.c
|
13 | 12 | +++ 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; |
15 | 14 | /* this doesn't need to be global; use PLy_current_execution_context() */
|
16 | 15 | static PLyExecutionContext *PLy_execution_contexts = NULL;
|
17 | 16 |
|
18 | 17 | +/* postgres backend handler for interruption */
|
19 | 18 | +static pqsigfunc coreIntHandler = 0;
|
20 | 19 | +static void PLy_handle_interrupt(int sig);
|
21 |
| -+ |
22 | 20 |
|
23 | 21 | void
|
24 | 22 | _PG_init(void)
|
25 |
| -@@ -81,6 +85,9 @@ _PG_init(void) |
| 23 | +@@ -81,6 +84,9 @@ _PG_init(void) |
26 | 24 | int **bitmask_ptr;
|
27 | 25 | const int **version_ptr;
|
28 | 26 |
|
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); |
31 | 29 | +
|
32 | 30 | /*
|
33 | 31 | * Set up a shared bitmask variable telling which Python version(s) are
|
34 | 32 | * 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 | ++ |
36 | 52 | MemoryContextDelete(context->scratch_ctx);
|
37 | 53 | PLy_free(context);
|
38 | 54 | }
|
39 | 55 | +
|
40 |
| -+void _PG_fini(void); |
41 | 56 | +void
|
42 | 57 | +_PG_fini(void)
|
43 | 58 | +{
|
44 |
| -+ if (coreIntHandler) { |
45 |
| -+ pqsignal(SIGINT, coreIntHandler); |
46 |
| -+ } |
| 59 | ++ // Restore previous SIGINT handler |
| 60 | ++ pqsignal(SIGINT, coreIntHandler); |
47 | 61 | +}
|
48 | 62 | +
|
49 | 63 | +static int
|
50 | 64 | +PLy_python_interruption_handler()
|
51 | 65 | +{
|
| 66 | ++ if (!PLy_pending_interrupt) { |
| 67 | ++ return 0; |
| 68 | ++ } |
| 69 | ++ |
| 70 | ++ PLy_pending_interrupt = 0; |
52 | 71 | + PyErr_SetString(PyExc_RuntimeError, "Execution of function interrupted by signal");
|
53 |
| -+ return 0; |
| 72 | ++ return -1; |
54 | 73 | +}
|
55 | 74 | +
|
56 | 75 | +static void
|
57 | 76 | +PLy_handle_interrupt(int sig)
|
58 | 77 | +{
|
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. |
63 | 87 | + (*coreIntHandler)(sig);
|
64 | 88 | + }
|
65 | 89 | +}
|
66 |
| -+ |
|
0 commit comments