Skip to content

Conversation

bcwarner
Copy link
Contributor

Adds some _after_fork() calls to reset locks for ObjectId and MongoClient, and some unit tests for both classes.

@bcwarner bcwarner marked this pull request as ready for review July 5, 2022 18:03
@bcwarner bcwarner requested a review from ShaneHarvey July 12, 2022 00:43
@bcwarner bcwarner requested a review from ShaneHarvey July 22, 2022 20:19
@bcwarner
Copy link
Contributor Author

bcwarner commented Aug 3, 2022

Currently fails on an pymongocrypt error that doesn't appear to be related.

@bcwarner bcwarner requested a review from ShaneHarvey August 3, 2022 16:48
@bcwarner bcwarner requested a review from ShaneHarvey August 4, 2022 17:22
bson/__init__.py Outdated


def _after_fork():
"""Releases the ObjectID lock in parent and child."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"in parent and child" -> "in child"

@@ -846,7 +857,11 @@ def target():
from pymongo.encryption import _Encrypter

self._encrypter = _Encrypter(self, self.__options.auto_encryption_opts)
self._timeout = options.timeout
self._timeout = self.__options.timeout
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest moving this section out of _init_deadlockables since it only needs to happen once in __init__, not after a fork:

        if connect:
            self._get_topology()
        self._encrypter = None
        if self.__options.auto_encryption_opts:
            from pymongo.encryption import _Encrypter

            self._encrypter = _Encrypter(self, self.__options.auto_encryption_opts)
        self._timeout = options.timeout

@@ -817,6 +821,14 @@ def __init__(
srv_max_hosts=srv_max_hosts,
)

self._init_deadlockables(connect)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest renaming to self._init_sdam or self._init_background

@@ -832,7 +844,6 @@ def target():
target=target,
name="pymongo_kill_cursors_thread",
)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra change here.

pymongo/lock.py Outdated
# References to instances of _create_lock
_forkable_locks: weakref.WeakSet = weakref.WeakSet()

_insertion_lock = threading.Lock()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WeakSet.add is implementing using set.add so it is threadsafe and we can remove _insertion_lock and _clients_lock:
https://github.com/python/cpython/blob/3.7/Lib/_weakrefset.py#L81-L84

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even asyncio uses WeakSet.add from multiple threads without a lock:
https://github.com/python/cpython/blob/3.7/Lib/asyncio/tasks.py#L860


def exit_cond():
with _insertion_lock:
return 0 # success
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to run an operation on the client in the child process here, like:

self.client.admin.command('ping')

pymongo/lock.py Outdated
return lock


def _release_locks(child: bool) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

child is no longer needed.

# This will run in the same thread as the fork was called.
# If we fork in a critical region on the same thread, it should break.
# This is fine since we would never call fork directly from a critical region.
os.register_at_fork(after_in_child=_after_fork_child, after_in_parent=_after_fork_parent)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after_in_parent is no longer needed.

Ben Warner added 2 commits August 4, 2022 16:14
Copy link
Member

@ShaneHarvey ShaneHarvey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@bcwarner bcwarner merged commit 3204290 into mongodb:master Aug 4, 2022
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

Successfully merging this pull request may close these issues.

4 participants