Merge pull request #1138 from ajbeamon/python-fix-signal-handler

Python now blocks on a future in Python rather than in native code to…
This commit is contained in:
Alec Grieser 2019-02-11 11:05:22 -08:00 committed by GitHub
commit 1d12618f7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 1 deletions

View File

@ -30,6 +30,7 @@ import datetime
import platform import platform
import os import os
import sys import sys
import multiprocessing
from fdb import six from fdb import six
@ -38,6 +39,8 @@ _network_thread_reentrant_lock = threading.RLock()
_open_file = open _open_file = open
_thread_local_storage = threading.local()
import weakref import weakref
@ -593,7 +596,27 @@ class Future(_FDBBase):
return bool(self.capi.fdb_future_is_ready(self.fpointer)) return bool(self.capi.fdb_future_is_ready(self.fpointer))
def block_until_ready(self): def block_until_ready(self):
self.capi.fdb_future_block_until_ready(self.fpointer) # Checking readiness is faster than using the callback, so it saves us time if we are already
# ready. It also doesn't add much to the cost of this function
if not self.is_ready():
# Blocking in the native client from the main thread prevents Python from handling signals.
# To avoid that behavior, we implement the blocking in Python using semaphores and on_ready.
# Using a Semaphore is faster than an Event, and we create only one per thread to avoid the
# cost of creating one every time.
semaphore = getattr(_thread_local_storage, 'future_block_semaphore', None)
if semaphore is None:
semaphore = multiprocessing.Semaphore(0)
_thread_local_storage.future_block_semaphore = semaphore
self.on_ready(lambda self: semaphore.release())
try:
semaphore.acquire()
except:
# If this semaphore didn't actually get released, then we need to replace our thread-local
# copy so that later callers still function correctly
_thread_local_storage.future_block_semaphore = multiprocessing.Semaphore(0)
raise
def on_ready(self, callback): def on_ready(self, callback):
def cb_and_delref(ignore): def cb_and_delref(ignore):

View File

@ -30,6 +30,7 @@ Bindings
* Golang: Deprecated ``fdb.StartNetwork``, ``fdb.Open``, ``fdb.MustOpen``, and ``fdb.CreateCluster`` and added ``fdb.OpenDatabase`` and ``fdb.MustOpenDatabase``. The preferred way to start the network and get a ``Database`` is by using ``FDB.OpenDatabase`` or ``FDB.OpenDefault``. `(PR #942) <https://github.com/apple/foundationdb/pull/942>`_ * Golang: Deprecated ``fdb.StartNetwork``, ``fdb.Open``, ``fdb.MustOpen``, and ``fdb.CreateCluster`` and added ``fdb.OpenDatabase`` and ``fdb.MustOpenDatabase``. The preferred way to start the network and get a ``Database`` is by using ``FDB.OpenDatabase`` or ``FDB.OpenDefault``. `(PR #942) <https://github.com/apple/foundationdb/pull/942>`_
* Flow: Deprecated ``API::createCluster`` and ``Cluster`` and added ``API::createDatabase``. The preferred way to get a ``Database`` is by using ``API::createDatabase``. `(PR #942) <https://github.com/apple/foundationdb/pull/942>`_ * Flow: Deprecated ``API::createCluster`` and ``Cluster`` and added ``API::createDatabase``. The preferred way to get a ``Database`` is by using ``API::createDatabase``. `(PR #942) <https://github.com/apple/foundationdb/pull/942>`_
* Golang: Added ``fdb.Printable`` to print a human-readable string for a given byte array. Add ``Key.String()``, which converts the ``Key`` to a ``string`` using the ``Printable`` function. `(PR #1010) <https://github.com/apple/foundationdb/pull/1010>`_ * Golang: Added ``fdb.Printable`` to print a human-readable string for a given byte array. Add ``Key.String()``, which converts the ``Key`` to a ``string`` using the ``Printable`` function. `(PR #1010) <https://github.com/apple/foundationdb/pull/1010>`_
* Python: Python signal handling didn't work when waiting on a future. In particular, pressing Ctrl-C would not successfully interrupt the program. `(PR #1138) <https://github.com/apple/foundationdb/pull/1138>`_
Other Changes Other Changes
------------- -------------