Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fdb.connect() spoils POSIX signal handlers #16

Open
o3bvv opened this issue May 26, 2020 · 2 comments
Open

fdb.connect() spoils POSIX signal handlers #16

o3bvv opened this issue May 26, 2020 · 2 comments

Comments

@o3bvv
Copy link

o3bvv commented May 26, 2020

Hello again,

I'm trying to investigate an issue with behavior signal handlers during and after invocation of fdb.connect().

I have a handler for SIGINT and SIGTERM which is used for application's graceful shutdown, e.g.:

import signal

def handler(signal_no, stack_frame):
   report_exit_request()
   notify_exit_subscribers()

signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)

The handler works perfectly before the call to fdb.connect(): it captures signals, reports the exit request, notifies subscribers and the main thread waits till all shut down work is finished:

2020-05-26 19:27:06.192580 +0000 [I] [27634 main] app: run… (version='1.0.0')
2020-05-26 19:27:06.193394 +0000 [D] [27634 main] state: loading…
2020-05-26 19:27:06.196915 +0000 [D] [27634 main] state: validating…
2020-05-26 19:27:06.198532 +0000 [D] [27634 main] state: loaded (version='1.0.0')
^C2020-05-26 19:27:07.293636 +0000 [D] [27634 main] exit handler: got exit request
2020-05-26 19:27:16.204282 +0000 [D] [27634 main] state: saving…
2020-05-26 19:27:16.207451 +0000 [D] [27634 main] state: saved
2020-05-26 19:27:16.207780 +0000 [I] [27634 main] app: done

But if fdb.connect() is invoked, the thread is killed immediately after receiving a signal:

2020-05-26 19:30:23.119293 +0000 [I] [27725 main] app: run… (version='1.0.0')
2020-05-26 19:30:23.119877 +0000 [D] [27725 main] state: loading…
2020-05-26 19:30:23.121167 +0000 [D] [27725 main] state: validating…
2020-05-26 19:30:23.122865 +0000 [D] [27725 main] state: loaded (version='1.0.0')
2020-05-26 19:30:23.123084 +0000 [D] [27725 main] db: connecting…
2020-05-26 19:30:23.123252 +0000 [D] [27725 main] db: connection attempt #1…
2020-05-26 19:30:23.264796 +0000 [D] [27725 main] db: connected (firebird_version='2.5.9.27139', ods_version=11.1, sql_dialect=1)
^C2020-05-26 19:30:25.173235 +0000 [D] [27725 main] exit handler: got exit request

As you can see, exit handler was invoked, but the app was killed before finishing (no log messages, as before). It's just a matter of chance that the handler's message managed to propagate to stdout via logger.

If the connection takes too long and the app gets a signal during connection, the thread just bails:

2020-05-26 19:34:07.990052 +0000 [I] [27755 main] app: run… (version='1.0.0')
2020-05-26 19:34:07.990657 +0000 [D] [27755 main] state: loading…
2020-05-26 19:34:07.993211 +0000 [D] [27755 main] state: validating…
2020-05-26 19:34:07.994736 +0000 [D] [27755 main] state: loaded (version='1.0.0')
2020-05-26 19:34:07.994903 +0000 [D] [27755 main] db: connecting…
2020-05-26 19:34:07.995045 +0000 [D] [27755 main] db: connection attempt #1…
^C

I've investigated signal handlers and masks before and after the call to fdb.connect() and they are the same. The rest of the app works as expected.

Noteworthy, setting signal handlers after the call to fdb.connect() once again makes the app to behave as expected. However, this cannot be considered as a workaround, as the app bails during the invocation of fdb.connect().

I've tried to investigate C++ sources of the driver and Python sources of its wrapper, but I couldn't spot any signal management inside them so far.

Could you please provide any suggestions regarding possible root cause?

My OS is macOS 10.15.1 and the driver is provided by FirebirdCS-2.5.9-27139-x86_64.pkg.

@pcisar
Copy link
Contributor

pcisar commented May 27, 2020

FDB does nothing with POSIX signal handlers, BUT it uses ctypes to work with Firebird client library that certainly does something to finalize so/ddl gracefuly. The library initialization is deferred until first request that needs it, i.e. connect, create_database or service.connect, so you can choose the client library to use and to allow fdb to be imported (or even installed) without Firebird installed. You can force the library initialization using load_api() call. See https://fdb.readthedocs.io/en/latest/reference.html#fdb.load_api

Try using load_api() before you install the signal handlers.

@o3bvv
Copy link
Author

o3bvv commented May 27, 2020

Yes, that's exactly what I've thought about and tried to do.

I've called fbd.load_api() before setting up the signal handler and I've commented out that call inside fbd.connect(): the app reacts as expected.

But calling fbd.connect() (even with disabled internal call to load_api()) still spoils things up and sending a signal to the app kills it immediately.

I've just checked the work on a windows server and it's fine, though:

paste.png

Of cource, on windows SetConsoleCtrlHandler() is used instead of signal(), but in my case it's the target platform, so I'm fine with postponing the issue at unix-like systems. Maybe it's a Python's bug, like this one: https://bugs.python.org/issue27889

I'd appreciate if you notify me in case you find a resolution for this or similar issue.

Thanks for your responses!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants