Open
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors Call Home (CH) thread lifecycle management to avoid shutdown-time leaks by switching from detached threads to joinable threads and introducing a centralized “stop if dispatched” helper used during config changes and server teardown. It also tightens lock/return-value handling in several CH-related paths and adds a warning when CH clients cannot be dispatched due to missing callbacks.
Changes:
- Make CH client threads joinable and introduce
nc_session_server_ch_client_dispatch_stop_if_dispatched()to stop+join them during config updates andnc_server_destroy(). - Improve Call Home reconcile behavior (stop deleted clients even if dispatch callbacks are missing) and add a WRN log when new CH clients won’t be dispatched.
- Minor session transport/logging improvements and library version bump.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/session.c | Adjusts CH lock handling during session free and improves an SSH EOF timeout warning message. |
| src/session_server.h | Restructures NC_ENABLED_SSH_TLS preprocessor guards around SSH-related declarations. |
| src/session_server.c | Implements CH thread stop+join helper, switches CH threads to joinable, and updates server destroy teardown ordering. |
| src/session_p.h | Adds CH thread pthread_t storage and declares the new internal stop helper. |
| src/server_config.c | Updates CH client reconciliation to use the centralized stop helper and adds a warning when dispatch callbacks are missing. |
| CMakeLists.txt | Bumps micro version / soversion. |
Comments suppressed due to low confidence (1)
src/session_server.c:3864
- With threads now joinable and stoppable via
thread_running, there is a race where a stop can be requested before the new thread executes and setsdata->thread_running = 1(the thread currently sets it unconditionally on startup). In that case, the stop request can be overwritten andpthread_join()in the stop helper may block indefinitely. Consider initializingarg->thread_runningunderarg->cond_lockbeforepthread_create()and updating the thread start logic to not flip it back to running if a stop was already requested.
pthread_cond_init(&arg->cond, NULL);
pthread_mutex_init(&arg->cond_lock, NULL);
/* CH THREADS WR LOCK */
if (nc_rwlock_lock(&server_opts.ch_threads_lock, NC_RWLOCK_WRITE, NC_CH_THREADS_LOCK_TIMEOUT, __func__) != 1) {
rc = -1;
goto cleanup;
}
ch_threads_lock = NC_RWLOCK_WRITE;
/* Append the thread data pointer to the global array.
* Pointer instead of struct so that server_opts.ch_thread_lock does not have to be
* locked everytime the arg is accessed */
LY_ARRAY_NEW_GOTO(NULL, server_opts.ch_threads, new_item, rc, cleanup);
*new_item = arg;
/* create the CH thread */
if ((r = pthread_create(&arg->tid, NULL, nc_ch_client_thread, arg))) {
ERR(NULL, "Creating a new thread failed (%s).", strerror(r));
/* remove from the array */
LY_ARRAY_DECREMENT_FREE(server_opts.ch_threads);
rc = -1;
goto cleanup;
}
/* arg is now owned by the thread */
arg = NULL;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Store thread IDs in ch_thread_arg to allow proper pthread_join when stopping threads. Add nc_session_server_ch_client_dispatch_stop_if_dispatched() to centralize thread stopping logic, fixing several locking issues: - Only unlock ch_lock if it was successfully acquired in nc_session_free() - Use config_update_lock to prevent data race in nc_server_destroy() - Properly handle config lock unlocking during thread join to avoid deadlock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change CH threads from detached to joinable (there was a memory leak where there wasn't enough time to free the thread when the server is stopping). The server now joins all the CH threads before ending.
Also fix multiple instances of incorrectly checking the return value of
nc_rwlock_lock().Added a function
nc_session_server_ch_client_dispatch_stop_if_dispatched()that joins these CH threads on config change or server destroy.Added a WRN log to inform the user that even though he created new CH clients, they won't be dispatched because required CBs were not set, previously this was done silently and threads of clients that were deleted weren't being stopped because of that.