Skip to content

Commit 2b1045d

Browse files
committed
connection: ensure sr_disconnect is called
If a client program does not call disconnect() it leaves resources open in sysrepo SHM. Use ffi.gc to register a destructor for the connection pointer. Since sr_connect can be a long operation (all YANG models must be parsed), if a signal occurs at that time, ffi.gc will not be called and no destructor will be registered. Block signals before calling sr_connect() and unblock them just after registering sr_disconnect. Signed-off-by: Robin Jarry <[email protected]>
1 parent 6e89ca7 commit 2b1045d

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

sysrepo/connection.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# SPDX-License-Identifier: BSD-3-Clause
33

44
import logging
5+
import signal
56
from typing import Optional, Sequence
67

78
import libyang
@@ -60,8 +61,12 @@ def __init__(
6061
if err_on_sched_fail:
6162
flags |= lib.SR_CONN_ERR_ON_SCHED_FAIL
6263
conn_p = ffi.new("sr_conn_ctx_t **")
63-
check_call(lib.sr_connect, flags, conn_p)
64-
self.cdata = conn_p[0]
64+
sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, range(1, signal.NSIG))
65+
try:
66+
check_call(lib.sr_connect, flags, conn_p)
67+
self.cdata = ffi.gc(conn_p[0], lib.sr_disconnect)
68+
finally:
69+
signal.pthread_sigmask(signal.SIG_SETMASK, sigmask)
6570

6671
def __enter__(self):
6772
return self
@@ -80,9 +85,9 @@ def disconnect(self) -> None:
8085
Connection and all its associated sessions and subscriptions can no longer be
8186
used even on error.
8287
"""
83-
try:
84-
check_call(lib.sr_disconnect, self.cdata)
85-
finally:
88+
if self.cdata is not None:
89+
if hasattr(ffi, "release"):
90+
ffi.release(self.cdata) # causes sr_disconnect to be called
8691
self.cdata = None
8792

8893
def start_session(self, datastore: str = "running") -> SysrepoSession:

0 commit comments

Comments
 (0)