Skip to content

Commit 8cf1d79

Browse files
Roytakmichalvasko
authored andcommitted
session server UPDATE move CH thread data free
Free the CH thread data in the main thread instead of the thread itself, because the data is allocated by the main thread, so it should also be destroyed by it.
1 parent 40fa70d commit 8cf1d79

1 file changed

Lines changed: 27 additions & 16 deletions

File tree

src/session_server.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3725,19 +3725,6 @@ nc_ch_client_thread(void *arg)
37253725
VRB(session, "Call Home client \"%s\" thread exit.", data->client_name);
37263726
free(cur_endpt_name);
37273727

3728-
/* find the client and clear thread pointer */
3729-
if (nc_rwlock_lock(&server_opts.config_lock, NC_RWLOCK_WRITE, NC_CONFIG_LOCK_TIMEOUT, __func__) == 1) {
3730-
client = nc_server_ch_client_get(data->client_name);
3731-
if (client && (client->thread == data)) {
3732-
client->thread = NULL;
3733-
}
3734-
nc_rwlock_unlock(&server_opts.config_lock, __func__);
3735-
}
3736-
3737-
free(data->client_name);
3738-
pthread_mutex_destroy(&data->cond_lock);
3739-
pthread_cond_destroy(&data->cond);
3740-
free(data);
37413728
return NULL;
37423729
}
37433730

@@ -3748,12 +3735,15 @@ nc_session_server_ch_client_dispatch_stop(struct nc_ch_client *ch_client)
37483735
struct nc_server_ch_thread_arg *thread_arg;
37493736
pthread_t tid;
37503737
enum nc_rwlock_mode config_lock_mode = NC_RWLOCK_WRITE;
3738+
char *ch_client_name = NULL;
37513739

37523740
if (!ch_client || !ch_client->thread) {
37533741
return 0;
37543742
}
37553743

37563744
thread_arg = ch_client->thread;
3745+
ch_client_name = strdup(thread_arg->client_name);
3746+
NC_CHECK_ERRMEM_GOTO(!ch_client_name, rc = 1, cleanup);
37573747

37583748
/* CH COND LOCK */
37593749
if (nc_mutex_lock(&thread_arg->cond_lock, NC_CH_COND_LOCK_TIMEOUT, __func__) != 1) {
@@ -3779,19 +3769,40 @@ nc_session_server_ch_client_dispatch_stop(struct nc_ch_client *ch_client)
37793769
/* wait for the thread to end */
37803770
r = pthread_join(tid, NULL);
37813771
if (r) {
3782-
ERR(NULL, "Joining Call Home client \"%s\" thread failed (%s).", ch_client->name, strerror(r));
3772+
ERR(NULL, "Joining Call Home client \"%s\" thread failed (%s).", ch_client_name, strerror(r));
3773+
rc = 1;
3774+
goto cleanup;
3775+
}
3776+
3777+
/* CONFIG WRITE LOCK - re-acquire to clear the thread pointer and free the thread data */
3778+
if (nc_rwlock_lock(&server_opts.config_lock, NC_RWLOCK_WRITE, NC_CONFIG_LOCK_TIMEOUT, __func__) != 1) {
3779+
/* if we fail, attempt to lock again in cleanup.
3780+
* ch thread data will cause a memory leak, but we should avoid a possible crash this way */
3781+
ERRINT;
37833782
rc = 1;
37843783
goto cleanup;
37853784
}
3785+
config_lock_mode = NC_RWLOCK_WRITE;
3786+
3787+
/* clear the thread pointer,
3788+
* ch_client MUST remain valid even though we unlocked config lock,
3789+
* because the caller MUST hold config apply mutex, so no one can change the config and free the client */
3790+
ch_client->thread = NULL;
3791+
3792+
/* free the thread data */
3793+
free(thread_arg->client_name);
3794+
pthread_mutex_destroy(&thread_arg->cond_lock);
3795+
pthread_cond_destroy(&thread_arg->cond);
3796+
free(thread_arg);
37863797

37873798
cleanup:
37883799
if (config_lock_mode == NC_RWLOCK_NONE) {
37893800
/* CONFIG LOCK - lock it back if we unlocked it. It MUST succeed, if the caller holds the config apply mutex */
3790-
if (nc_rwlock_lock(&server_opts.config_lock, NC_RWLOCK_WRITE, -1, __func__) != 1) {
3801+
if (nc_rwlock_lock(&server_opts.config_lock, NC_RWLOCK_WRITE, NC_CONFIG_LOCK_TIMEOUT, __func__) != 1) {
37913802
ERRINT;
37923803
}
37933804
}
3794-
3805+
free(ch_client_name);
37953806
return rc;
37963807
}
37973808

0 commit comments

Comments
 (0)