More robust signal handling for non-M main programs
Final Release Note
SIGINT/SIGTERM/SIGQUIT signals are specially handled in case of a non-YottaDB main application/program (e.g., a Simple API application)
- The first call by the main program into YottaDB establishes YottaDB signal handlers for these signals overriding any signal handlers established by the main program.
- On receipt of one of these signals, the YottaDB signal handler checks if the database engine is in a state where it can be safely interrupted.
- If not safe, YottaDB defers handling the signal until the database engine is in a safe state.
- If safe, the YottaDB signal handler invokes the signal handler, if any, defined by the main program. There are two special cases:
- If the main program has not established a signal handler for these signals, the default signal handler (
SIG_DFL
) would be in effect. Since these signals are considered fatal/terminating signals by YottaDB, it terminates the process. - If the main program has explicitly set these signals to be ignored (
SIG_IGN
), then YottaDB signal does not drive any application signal handler for these signals.
- If the main program has not established a signal handler for these signals, the default signal handler (
A consequence of this behavior for Flask applications is that:
- Ctrl-C on an interactive Flask application, that uses the YDBPython wrapper to make calls into YottaDB, stops the application because Flask sets up a signal handler for Ctrl-C (SIGINT) to terminate the process. Previously, repeated Ctrl-C did nothing to the application until the next YottaDB call at which point the process would terminate.
- SIGTERM on a non-interactive Flask application, that uses the YDBPython wrapper to make calls into YottaDB, terminates the application because Flask sets the SIGTERM handler to
SIG_DFL
(the default signal handler). Previously, one had to send 3 SIGTERM signals to the Flask application to terminate it.
Additionally, a non-YottaDB main program that uses non-threaded Simple API functions to make calls into YottaDB correctly handles all signals in the thread that receives the signal. Previously, many signals (including but not limited to SIGINT/SIGTERM/SIGQUIT) would be ignored) owing to an attempt to forward the signal to the thread that originally did the ydb_init()
call, in case that thread no longer exists.
Description
Follow instructions here: https://gitlab.com/YottaDB/Demo/YDBApron/-/blob/ece7ac781f886bc032a6300665ab4b50163291a1/README.md to set-up the Flask application.
CTRL-C normally works if you don't visit any page that uses YottaDB
Visit e.g. /recipes/list
. That calls YottaDB.
Now go to the terminal, and press CTRL-C multiple times. You will core out.
Backtrace:
#0 0x00007f91fb522131 in pthread_kill () from /lib64/libpthread.so.0
#1 0x00007f91f7bd5909 in gtm_dump_core () at /Distrib/YottaDB/V989_R139/sr_unix/gtm_dump_core.c:74
#2 0x00007f91f7bd6e42 in gtm_fork_n_core () at /Distrib/YottaDB/V989_R139/sr_unix/gtm_fork_n_core.c:163
#3 0x00007f91f7baf991 in ch_cond_core () at /Distrib/YottaDB/V989_R139/sr_unix/ch_cond_core.c:80
#4 0x00007f91f7ce2665 in rts_error_va (csa=0x0, argcnt=7, var=0x56234c022f20) at /Distrib/YottaDB/V989_R139/sr_unix/rts_error.c:198
#5 0x00007f91f7ce2b5e in rts_error_csa (csa=0x0, argcnt=7) at /Distrib/YottaDB/V989_R139/sr_unix/rts_error.c:99
#6 0x00007f91f81b8f1a in generic_signal_handler (sig=2, info=0x56234c0233f0, context=0x56234c0232c0, is_os_signal_handler=1) at /Distrib/YottaDB/V989_R139/sr_unix/generic_signal_handler.c:198
#7 0x00007f91f7db35ba in ydb_os_signal_handler (sig=2, info=0x56234c0233f0, context=0x56234c0232c0) at /Distrib/YottaDB/V989_R139/sr_unix/ydb_os_signal_handler.c:85
#8 <signal handler called>
#9 0x00007f91fb4250a9 in poll () from /lib64/libc.so.6
#10 0x00007f91faeb49b9 in ?? () from /usr/lib64/python3.6/lib-dynload/select.cpython-36m-x86_64-linux-gnu.so
#11 0x00007f91fb5ec08d in _PyCFunction_FastCallDict () from /usr/lib64/libpython3.6m.so.1.0
#12 0x00007f91fb65da72 in ?? () from /usr/lib64/libpython3.6m.so.1.0
.
.
#81 0x00007f91fb6a0031 in Py_Main () from /usr/lib64/libpython3.6m.so.1.0
#82 0x000056234ac05c90 in main ()
Draft Release Note
SIGINT/SIGTERM/SIGQUIT signals are now specially handled in case of a non-YottaDB main application/program (for example, a Simple API application).
- The first call by the main program into YottaDB would establish signal handlers for these signals overriding any signal handlers established by the main program for these same signals.
- On receipt of any of these signals, the YottaDB signal handler now checks if it is safe to interrupt the program from the database perspective.
- If not safe, it will continue to defer the signal like it used to previously.
- If safe, the YottaDB signal handler now invokes any signal handlers defined by the main program.
- If the main program had not established a signal handler for these signals, the default signal handler (
SIG_DFL
) would be in effect and since these signals are considered fatal/terminating signals by YottaDB, it now terminates the process. - If the main program had explicitly set these signals to be ignored (
SIG_IGN
), then the YottaDB signal handler does not drive any application signal handler for these signals.
A consequence of these changes is that
- Ctrl-C on an interactive Flask application, that used the YDBPython wrapper to make calls into YottaDB, now stops the application because the Flask application had set up a signal handler for Ctrl-C (SIGINT) to terminate the process. Previously, repeated Ctrl-C used to do nothing to the application until the next YottaDB call at which point the process would terminate.
- SIGTERM on a non-interactive Flask application, that used the YDBPython wrapper to make calls into YottaDB, now terminates the application because the SIGTERM signal handler was set to
SIG_DFL
(the default signal handler) in the Flask application and the default action of the SIGTERM signal is to terminate the process. Previously, one had to send 3 SIGTERM signals to the Flask application to terminate it.
Additionally, a non-YottaDB main program that uses non-threaded Simple API functions to make calls into YottaDB now correctly handles all signals in the thread that receives the signal. Previously, a lot of signals (including but not limited to SIGINT/SIGTERM/SIGQUIT) would not be handled (i.e. ignored) due to an attempt to forward the signal to the thread that originally did the ydb_init()
call in case that thread no longer exists.