Skip to content

Commit

Permalink
Avoid deadlock in getaddrinfo
Browse files Browse the repository at this point in the history
getaddrinfo may use an internal lock that, in case of a concurrent
fork, may be left in locked state and cause child process to deadlock.
  • Loading branch information
vickenty committed Aug 16, 2024
1 parent 7ed936c commit fb20759
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions datadog/dogstatsd/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1531,8 +1531,15 @@ def pre_fork(self):
self._stop_flush_thread()
self._stop_sender_thread()

# Prevent concurrent calls to system libraries (notably
# getaddrinfo) which may leave internal locks in a locked
# state and deadlock the child.
self._socket_lock.acquire()

def post_fork_parent(self):
"""Restore the client state after a fork in the parent process."""
self._socket_lock.release()

if self._disable_aggregating:
self._start_flush_thread(
self._flush_interval,
Expand All @@ -1548,21 +1555,17 @@ def post_fork_parent(self):

def post_fork_child(self):
"""Restore the client state after a fork in the child process."""
self._socket_lock.release()
self._config_lock.release()

# Discard the locks that could have been locked at the time
# when we forked. This may cause inconsistent internal state,
# which we will fix in the next steps.
self._socket_lock = Lock()
self._buffer_lock = RLock()

# Reset the buffer so we don't send metrics from the parent
# process. Also makes sure buffer properties are consistent.
self._reset_buffer()
# Execute the socket_path setter to reconcile transport and
# payload size properties in respect to socket_path value.
self.socket_path = self.socket_path
self.close_socket()

with self._config_lock:
if self._disable_aggregating:
Expand Down

0 comments on commit fb20759

Please sign in to comment.