@@ -73,6 +73,7 @@ static struct nc_client_context context_main = {
7373 .max_probes = 10 ,
7474 .probe_interval = 5
7575 },
76+ .opts .monitoring_thread_data .lock = PTHREAD_MUTEX_INITIALIZER ,
7677#ifdef NC_ENABLED_SSH_TLS
7778 .ssh_opts = {
7879 .auth_pref = {{NC_SSH_AUTH_INTERACTIVE , 1 }, {NC_SSH_AUTH_PASSWORD , 2 }, {NC_SSH_AUTH_PUBLICKEY , 3 }},
@@ -192,6 +193,10 @@ nc_client_context_location(void)
192193 e -> ssh_ch_opts .auth_pref [2 ].value = 3 ;
193194#endif /* NC_ENABLED_SSH_TLS */
194195 }
196+
197+ /* init the monitoring thread data lock */
198+ pthread_mutex_init (& e -> opts .monitoring_thread_data .lock , NULL );
199+
195200 pthread_setspecific (nc_client_context_key , e );
196201 }
197202
@@ -1460,11 +1465,9 @@ nc_connect_inout(int fdin, int fdout, struct ly_ctx *ctx)
14601465 goto fail ;
14611466 }
14621467
1463- /* start monitoring the session */
1464- if (client_opts .monitoring_thread_data ) {
1465- if (nc_client_monitoring_session_start (session )) {
1466- goto fail ;
1467- }
1468+ /* start monitoring the session if the monitoring thread is running */
1469+ if (nc_client_monitoring_session_start (session )) {
1470+ goto fail ;
14681471 }
14691472
14701473 return session ;
@@ -1544,11 +1547,9 @@ nc_connect_unix(const char *address, struct ly_ctx *ctx)
15441547 goto fail ;
15451548 }
15461549
1547- /* start monitoring the session */
1548- if (client_opts .monitoring_thread_data ) {
1549- if (nc_client_monitoring_session_start (session )) {
1550- goto fail ;
1551- }
1550+ /* start monitoring the session if the monitoring thread is running */
1551+ if (nc_client_monitoring_session_start (session )) {
1552+ goto fail ;
15521553 }
15531554
15541555 return session ;
@@ -3248,7 +3249,7 @@ nc_client_monitoring_get_session_fd(struct nc_session *session)
32483249{
32493250 int fd = -1 ;
32503251
3251- switch (( session -> ti_type ) ) {
3252+ switch (session -> ti_type ) {
32523253 case NC_TI_FD :
32533254 fd = session -> ti .fd .in ;
32543255 break ;
@@ -3263,8 +3264,8 @@ nc_client_monitoring_get_session_fd(struct nc_session *session)
32633264 fd = nc_tls_get_fd_wrap (session );
32643265 break ;
32653266#endif /* NC_ENABLED_SSH_TLS */
3266- default :
3267- ERR ( session , "Unknown transport type." );
3267+ case NC_TI_NONE :
3268+ /* invalid */
32683269 break ;
32693270 }
32703271
@@ -3278,21 +3279,19 @@ nc_client_monitoring_session_start(struct nc_session *session)
32783279 struct nc_client_monitoring_thread_arg * mtarg ;
32793280 void * tmp , * tmp2 ;
32803281
3281- mtarg = client_opts .monitoring_thread_data ;
3282- if (!mtarg ) {
3283- ERRINT ;
3284- return 1 ;
3282+ /* LOCK */
3283+ pthread_mutex_lock (& client_opts .monitoring_thread_data .lock );
3284+
3285+ /* check if the monitoring thread is running */
3286+ if (!client_opts .monitoring_thread_data .thread_running ) {
3287+ goto cleanup ;
32853288 }
32863289
3290+ mtarg = & client_opts .monitoring_thread_data ;
3291+
32873292 /* get the session's file descriptor */
32883293 fd = nc_client_monitoring_get_session_fd (session );
3289- if (fd == -1 ) {
3290- ERR (session , "Unable to monitor an invalid file descriptor." );
3291- return 1 ;
3292- }
3293-
3294- /* LOCK */
3295- pthread_mutex_lock (& mtarg -> lock );
3294+ assert (fd != -1 );
32963295
32973296 /* if realloc fails, keep the original sessions without adding the new one */
32983297 tmp = realloc (mtarg -> sessions , (mtarg -> session_count + 1 ) * sizeof * mtarg -> sessions );
@@ -3325,17 +3324,13 @@ nc_client_monitoring_session_stop(struct nc_session *session, int lock)
33253324 int i ;
33263325 struct nc_client_monitoring_thread_arg * mtarg ;
33273326
3328- mtarg = client_opts .monitoring_thread_data ;
3329- if (!mtarg ) {
3330- ERRINT ;
3331- return ;
3332- }
3333-
33343327 if (lock ) {
33353328 /* LOCK */
3336- pthread_mutex_lock (& mtarg -> lock );
3329+ pthread_mutex_lock (& client_opts . monitoring_thread_data . lock );
33373330 }
33383331
3332+ mtarg = & client_opts .monitoring_thread_data ;
3333+
33393334 /* session is no longer monitored (is being freed) */
33403335 if (!(session -> flags & NC_SESSION_CLIENT_MONITORED )) {
33413336 goto cleanup ;
@@ -3392,15 +3387,10 @@ nc_client_monitoring_thread(void *arg)
33923387 /* set this thread's context to the one from the thread that started the monitoring thread */
33933388 nc_client_set_thread_context (arg );
33943389
3395- /* so that both threads share the same opts */
3396- mtarg = client_opts .monitoring_thread_data ;
3397- if (!mtarg ) {
3398- ERRINT ;
3399- return NULL ;
3400- }
3401-
34023390 /* LOCK */
3403- pthread_mutex_lock (& mtarg -> lock );
3391+ pthread_mutex_lock (& client_opts .monitoring_thread_data .lock );
3392+
3393+ mtarg = & client_opts .monitoring_thread_data ;
34043394
34053395 while (mtarg -> thread_running ) {
34063396 if (!mtarg -> session_count ) {
@@ -3463,19 +3453,17 @@ nc_client_monitoring_thread_start(nc_client_monitoring_clb monitoring_clb, void
34633453
34643454 NC_CHECK_ARG_RET (NULL , monitoring_clb , 1 );
34653455
3466- if (client_opts .monitoring_thread_data ) {
3456+ /* LOCK */
3457+ pthread_mutex_lock (& client_opts .monitoring_thread_data .lock );
3458+ if (client_opts .monitoring_thread_data .thread_running ) {
34673459 ERR (NULL , "Client monitoring thread is already running." );
3468- return 1 ;
3460+ ret = 1 ;
3461+ goto cleanup ;
34693462 }
34703463
3471- client_opts .monitoring_thread_data = calloc (1 , sizeof * client_opts .monitoring_thread_data );
3472- NC_CHECK_ERRMEM_RET (!client_opts .monitoring_thread_data , 1 );
3473-
3474- client_opts .monitoring_thread_data -> clb = monitoring_clb ;
3475- client_opts .monitoring_thread_data -> clb_data = user_data ;
3476- client_opts .monitoring_thread_data -> clb_free_data = free_data ;
3477-
3478- pthread_mutex_init (& client_opts .monitoring_thread_data -> lock , NULL );
3464+ client_opts .monitoring_thread_data .clb = monitoring_clb ;
3465+ client_opts .monitoring_thread_data .clb_data = user_data ;
3466+ client_opts .monitoring_thread_data .clb_free_data = free_data ;
34793467
34803468 /* get the current thread context, so that the monitoring thread can use it */
34813469 ctx = nc_client_get_thread_context ();
@@ -3485,9 +3473,9 @@ nc_client_monitoring_thread_start(nc_client_monitoring_clb monitoring_clb, void
34853473 goto cleanup ;
34863474 }
34873475
3488- client_opts .monitoring_thread_data -> thread_running = 1 ;
3476+ client_opts .monitoring_thread_data . thread_running = 1 ;
34893477
3490- r = pthread_create (& client_opts .monitoring_thread_data -> tid , NULL ,
3478+ r = pthread_create (& client_opts .monitoring_thread_data . tid , NULL ,
34913479 nc_client_monitoring_thread , ctx );
34923480 if (r ) {
34933481 ERR (NULL , "Failed to create the client monitoring thread (%s)." , strerror (r ));
@@ -3496,11 +3484,8 @@ nc_client_monitoring_thread_start(nc_client_monitoring_clb monitoring_clb, void
34963484 }
34973485
34983486cleanup :
3499- if (ret ) {
3500- pthread_mutex_destroy (& client_opts .monitoring_thread_data -> lock );
3501- free (client_opts .monitoring_thread_data );
3502- }
3503-
3487+ /* UNLOCK */
3488+ pthread_mutex_unlock (& client_opts .monitoring_thread_data .lock );
35043489 return ret ;
35053490}
35063491
@@ -3511,19 +3496,20 @@ nc_client_monitoring_thread_stop(void)
35113496 pthread_t tid ;
35123497 struct nc_client_monitoring_thread_arg * mtarg ;
35133498
3514- if (!client_opts .monitoring_thread_data ) {
3499+ /* LOCK */
3500+ pthread_mutex_lock (& client_opts .monitoring_thread_data .lock );
3501+ if (!client_opts .monitoring_thread_data .thread_running ) {
35153502 ERR (NULL , "Client monitoring thread is not running." );
3503+
3504+ /* UNLOCK */
3505+ pthread_mutex_unlock (& client_opts .monitoring_thread_data .lock );
35163506 return ;
35173507 }
35183508
3519- mtarg = client_opts .monitoring_thread_data ;
3520-
3521- /* LOCK */
3522- pthread_mutex_lock (& mtarg -> lock );
3509+ mtarg = & client_opts .monitoring_thread_data ;
35233510
35243511 mtarg -> thread_running = 0 ;
35253512 tid = mtarg -> tid ;
3526- client_opts .monitoring_thread_data = NULL ;
35273513
35283514 /* remove the flag from the session while the lock is held */
35293515 for (i = 0 ; i < mtarg -> session_count ; i ++ ) {
@@ -3538,14 +3524,24 @@ nc_client_monitoring_thread_stop(void)
35383524 ERR (NULL , "Failed to join the client monitoring thread (%s)." , strerror (r ));
35393525 }
35403526
3527+ /* LOCK */
3528+ pthread_mutex_lock (& mtarg -> lock );
3529+
35413530 if (mtarg -> clb_free_data ) {
35423531 mtarg -> clb_free_data (mtarg -> clb_data );
35433532 }
3533+ mtarg -> clb = NULL ;
3534+ mtarg -> clb_data = NULL ;
3535+ mtarg -> clb_free_data = NULL ;
3536+
35443537 free (mtarg -> sessions );
3538+ mtarg -> sessions = NULL ;
3539+
35453540 free (mtarg -> pfds );
3546- pthread_mutex_destroy ( & mtarg -> lock ) ;
3541+ mtarg -> pfds = NULL ;
35473542
3548- free (mtarg );
3543+ /* UNLOCK */
3544+ pthread_mutex_unlock (& mtarg -> lock );
35493545}
35503546
35513547API void
0 commit comments