Skip to content

Commit 4b4a6ab

Browse files
committed
fix(driver): defer TLS config creation to prevent nng fork panic
1 parent f689a56 commit 4b4a6ab

2 files changed

Lines changed: 12 additions & 10 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project follows versions of format `{year}.{month}.{patch_number}`.
1010
### Fixed
1111

1212
- `qpi-ui`: Fixed an issue in the admin dashboard where dismissed system notifications reappeared on page refresh. Dismissals are now correctly persisted via proxy user API requests.
13+
- `qpi-driver`: Fixed a `panic: nng is not fork-reentrant safe` error in multiprocessing environments by deferring the NNG TLSConfig initialization until after the worker processes have forked.
1314

1415
## [0.0.33] - 2026-06-27
1516

qpi-driver/qpi_driver/driver.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ def send_results(
198198
result_queue: multiprocessing.Queue,
199199
res_port: int,
200200
nng_host: str,
201+
qpi_addr: str,
202+
ca_fingerprint: str,
201203
ca_file_path: Path,
202204
) -> None:
203205
"""Result sender process: reads Qiskit-format result dicts from result_queue
@@ -207,6 +209,8 @@ def send_results(
207209
result_queue: Queue used to receive result dicts from the worker.
208210
res_port: Port allocated for the NNG PUSH socket to return results.
209211
nng_host: Hostname or IP of the Go PocketBase server (for NNG TCP connections).
212+
qpi_addr: Full URL of the QPI server.
213+
ca_fingerprint: the fingerprint to verify that the downloaded CA file is the right one
210214
ca_file_path: Path to the CA certificate file for TLS connections.
211215
"""
212216
logging.basicConfig(
@@ -220,11 +224,7 @@ def send_results(
220224
addr = f"tls+tcp://{nng_host}:{res_port}"
221225
rs_log.info("Connecting NNG PUSH → %s", addr)
222226

223-
tls_config = TLSConfig(
224-
TLSConfig.MODE_CLIENT,
225-
server_name=nng_host,
226-
ca_files=ca_file_path.as_posix(),
227-
)
227+
tls_config = _get_tls_config(qpi_addr, ca_fingerprint, ca_file_path)
228228

229229
with pynng.Push0(tls_config=tls_config) as sock:
230230
sock.dial(addr, block=True)
@@ -341,25 +341,26 @@ def run_driver(
341341
)
342342
worker.start()
343343

344-
# 4. Ensure TLS CA cert is downloaded before starting the result sender process
345-
tls_config = _get_tls_config(
346-
qpi_addr, ca_fingerprint=ca_fingerprint, ca_file_path=ca_file_path
347-
)
348-
349344
# Start Result Sender Process
350345
result_sender = multiprocessing.Process(
351346
target=send_results,
352347
kwargs={
353348
"result_queue": result_queue,
354349
"res_port": res_port,
355350
"nng_host": nng_host,
351+
"qpi_addr": qpi_addr,
352+
"ca_fingerprint": ca_fingerprint,
356353
"ca_file_path": ca_file_path,
357354
},
358355
name="QPI-ResultSender",
359356
daemon=True,
360357
)
361358
result_sender.start()
362359

360+
tls_config = _get_tls_config(
361+
qpi_addr, ca_fingerprint=ca_fingerprint, ca_file_path=ca_file_path
362+
)
363+
363364
addr = f"tls+tcp://{nng_host}:{cmd_port}"
364365
log.info("Connecting NNG PULL → %s", addr)
365366

0 commit comments

Comments
 (0)