From 79beaa400429d84d85805df25a69ac4c3e23a520 Mon Sep 17 00:00:00 2001 From: Thomas Sader Date: Sat, 29 Jun 2024 18:07:09 +0200 Subject: [PATCH] Allow python threads and async io --- src/main.c | 4 ++++ src/mod/modvals.h | 6 +++++- src/mod/python.mod/python.c | 16 ++++++++++++++++ src/net.c | 3 +++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 82ed9ef80..e78b18dd3 100644 --- a/src/main.c +++ b/src/main.c @@ -1023,6 +1023,10 @@ int main(int arg_c, char **arg_v) sigaction(SIGILL, &sv, NULL); sv.sa_handler = got_alarm; sigaction(SIGALRM, &sv, NULL); + // Added for python.mod because the _signal handler otherwise overwrites it + // see https://discuss.python.org/t/asyncio-skipping-signal-handling-setup-during-import-for-python-embedded-context/37054/6 + sv.sa_handler = got_term; + sigaction(SIGINT, &sv, NULL); /* Initialize variables and stuff */ now = time(NULL); diff --git a/src/mod/modvals.h b/src/mod/modvals.h index 6b955cad3..a840e09cf 100644 --- a/src/mod/modvals.h +++ b/src/mod/modvals.h @@ -39,7 +39,11 @@ #define HOOK_LOADED 13 #define HOOK_BACKUP 14 #define HOOK_DIE 15 -#define REAL_HOOKS 16 +#define HOOK_PRE_SELECT 16 +#define HOOK_POST_SELECT 17 + +#define REAL_HOOKS 18 + #define HOOK_SHAREOUT 105 #define HOOK_SHAREIN 106 #define HOOK_ENCRYPT_PASS 107 diff --git a/src/mod/python.mod/python.c b/src/mod/python.mod/python.c index 7a4ed7fce..9ce10d673 100644 --- a/src/mod/python.mod/python.c +++ b/src/mod/python.mod/python.c @@ -43,6 +43,7 @@ static PyObject *pirp, *pglobals; #undef global static Function *global = NULL, *irc_funcs = NULL; +static PyThreadState *_pythreadsave; #include "src/mod/python.mod/pycmds.c" #include "src/mod/python.mod/tclpython.c" @@ -53,6 +54,16 @@ static int python_expmem() return 0; // TODO } +static int python_gil_unlock() { + _pythreadsave = PyEval_SaveThread(); + return 0; +} + +static int python_gil_lock() { + PyEval_RestoreThread(_pythreadsave); + return 0; +} + // TODO: Do we really have to exit eggdrop on module load failure? static void init_python() { PyObject *pmodule; @@ -119,6 +130,8 @@ static void python_report(int idx, int details) static char *python_close() { Context; + del_hook(HOOK_PRE_SELECT, (Function)python_gil_unlock); + del_hook(HOOK_POST_SELECT, (Function)python_gil_lock); kill_python(); rem_builtins(H_dcc, mydcc); rem_tcl_commands(my_tcl_cmds); @@ -160,5 +173,8 @@ char *python_start(Function *global_funcs) /* Add command table to bind list */ add_builtins(H_dcc, mydcc); add_tcl_commands(my_tcl_cmds); + add_hook(HOOK_PRE_SELECT, (Function)python_gil_unlock); + add_hook(HOOK_POST_SELECT, (Function)python_gil_lock); + return NULL; } diff --git a/src/net.c b/src/net.c index 3e23acb97..6ec1d5b3a 100644 --- a/src/net.c +++ b/src/net.c @@ -27,6 +27,7 @@ #include #include "main.h" +#include "modules.h" #include #include #include @@ -924,11 +925,13 @@ int sockread(char *s, int *len, sock_list *slist, int slistmax, int tclonly) t.tv_sec = td->blocktime.tv_sec; t.tv_usec = td->blocktime.tv_usec; + call_hook(HOOK_PRE_SELECT); x = select((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 (maxfd_r >= 0 ? &fdr : NULL), SELECT_TYPE_ARG234 (maxfd_w >= 0 ? &fdw : NULL), SELECT_TYPE_ARG234 (maxfd_e >= 0 ? &fde : NULL), SELECT_TYPE_ARG5 &t); + call_hook(HOOK_POST_SELECT); if (x == -1) return -2; /* socket error */ if (x == 0)