@@ -5870,6 +5870,41 @@ nc_server_config_cert_exp_notif_thread_wakeup(void)
58705870
58715871#endif /* NC_ENABLED_SSH_TLS */
58725872
5873+ /**
5874+ * @brief Wait for any pending updates to complete, then mark the server as "applying configuration".
5875+ *
5876+ * @return 0 on success, 1 on timeout.
5877+ */
5878+ static int
5879+ nc_server_config_update_start (void )
5880+ {
5881+ struct timespec ts_timeout ;
5882+
5883+ /* get the time point of timeout */
5884+ nc_timeouttime_get (& ts_timeout , NC_SERVER_CONFIG_UPDATE_WAIT_TIMEOUT_SEC * 1000 );
5885+
5886+ while (nc_timeouttime_cur_diff (& ts_timeout ) > 0 ) {
5887+ /* WR LOCK */
5888+ pthread_rwlock_wrlock (& server_opts .config_lock );
5889+
5890+ if (!server_opts .applying_config ) {
5891+ /* set the flag and end */
5892+ server_opts .applying_config = 1 ;
5893+
5894+ /* UNLOCK */
5895+ pthread_rwlock_unlock (& server_opts .config_lock );
5896+ return 0 ;
5897+ }
5898+
5899+ /* UNLOCK and wait */
5900+ pthread_rwlock_unlock (& server_opts .config_lock );
5901+ usleep (NC_TIMEOUT_STEP );
5902+ }
5903+
5904+ ERR (NULL , "Timeout expired while waiting for the server to apply the previous configuration." );
5905+ return 1 ;
5906+ }
5907+
58735908API int
58745909nc_server_config_setup_diff (const struct lyd_node * data )
58755910{
@@ -5878,6 +5913,9 @@ nc_server_config_setup_diff(const struct lyd_node *data)
58785913
58795914 NC_CHECK_ARG_RET (NULL , data , 1 );
58805915
5916+ /* wait until previous is done, then mark us as applying */
5917+ NC_CHECK_RET (nc_server_config_update_start ());
5918+
58815919 /* CONFIG RD LOCK */
58825920 pthread_rwlock_rdlock (& server_opts .config_lock );
58835921
@@ -5919,11 +5957,10 @@ nc_server_config_setup_diff(const struct lyd_node *data)
59195957 ERR (NULL , "Dispatching new call-home threads failed." ), cleanup_unlock );
59205958#endif /* NC_ENABLED_SSH_TLS */
59215959
5922- /* free the old config */
5960+ /* swap: free old, keep new, zero out the copy just in case to avoid double free */
59235961 nc_server_config_free (& server_opts .config );
5924-
5925- /* replace it with the new one */
59265962 server_opts .config = config_copy ;
5963+ memset (& config_copy , 0 , sizeof config_copy );
59275964
59285965#ifdef NC_ENABLED_SSH_TLS
59295966 /* wake up the cert expiration notif thread */
@@ -5940,6 +5977,11 @@ nc_server_config_setup_diff(const struct lyd_node *data)
59405977 nc_server_config_free (& config_copy );
59415978 }
59425979
5980+ /* clear the applying_config flag */
5981+ pthread_rwlock_wrlock (& server_opts .config_lock );
5982+ server_opts .applying_config = 0 ;
5983+ pthread_rwlock_unlock (& server_opts .config_lock );
5984+
59435985 return ret ;
59445986}
59455987
@@ -5952,6 +5994,9 @@ nc_server_config_setup_data(const struct lyd_node *data)
59525994
59535995 NC_CHECK_ARG_RET (NULL , data , 1 );
59545996
5997+ /* wait until previous is done, then mark us as applying */
5998+ NC_CHECK_RET (nc_server_config_update_start ());
5999+
59556000 /* check that the config data are not diff (no op attr) */
59566001 LY_LIST_FOR (data , tree ) {
59576002 LYD_TREE_DFS_BEGIN (tree , iter ) {
@@ -6000,11 +6045,10 @@ nc_server_config_setup_data(const struct lyd_node *data)
60006045 ERR (NULL , "Dispatching new call-home connections failed." ), cleanup_unlock );
60016046#endif /* NC_ENABLED_SSH_TLS */
60026047
6003- /* free the old config */
6048+ /* swap: free old, keep new, zero out the copy just in case to avoid double free */
60046049 nc_server_config_free (& server_opts .config );
6005-
6006- /* replace it with the new one */
60076050 server_opts .config = config ;
6051+ memset (& config , 0 , sizeof config );
60086052
60096053#ifdef NC_ENABLED_SSH_TLS
60106054 /* wake up the cert expiration notif thread */
@@ -6021,6 +6065,11 @@ nc_server_config_setup_data(const struct lyd_node *data)
60216065 nc_server_config_free (& config );
60226066 }
60236067
6068+ /* clear the applying_config flag */
6069+ pthread_rwlock_wrlock (& server_opts .config_lock );
6070+ server_opts .applying_config = 0 ;
6071+ pthread_rwlock_unlock (& server_opts .config_lock );
6072+
60246073 return ret ;
60256074}
60266075
0 commit comments