Skip to content

Commit

Permalink
connection: ensure sr_disconnect is called
Browse files Browse the repository at this point in the history
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 <robin.jarry@6wind.com>
  • Loading branch information
rjarry committed Oct 16, 2020
1 parent 6e89ca7 commit 2b1045d
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions sysrepo/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-License-Identifier: BSD-3-Clause

import logging
import signal
from typing import Optional, Sequence

import libyang
Expand Down Expand Up @@ -60,8 +61,12 @@ def __init__(
if err_on_sched_fail:
flags |= lib.SR_CONN_ERR_ON_SCHED_FAIL
conn_p = ffi.new("sr_conn_ctx_t **")
check_call(lib.sr_connect, flags, conn_p)
self.cdata = conn_p[0]
sigmask = signal.pthread_sigmask(signal.SIG_BLOCK, range(1, signal.NSIG))
try:
check_call(lib.sr_connect, flags, conn_p)
self.cdata = ffi.gc(conn_p[0], lib.sr_disconnect)
finally:
signal.pthread_sigmask(signal.SIG_SETMASK, sigmask)

def __enter__(self):
return self
Expand All @@ -80,9 +85,9 @@ def disconnect(self) -> None:
Connection and all its associated sessions and subscriptions can no longer be
used even on error.
"""
try:
check_call(lib.sr_disconnect, self.cdata)
finally:
if self.cdata is not None:
if hasattr(ffi, "release"):
ffi.release(self.cdata) # causes sr_disconnect to be called
self.cdata = None

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

0 comments on commit 2b1045d

Please sign in to comment.