diff --git a/src/gvmd.c b/src/gvmd.c index cd567a30c..34a720efd 100644 --- a/src/gvmd.c +++ b/src/gvmd.c @@ -1179,11 +1179,13 @@ update_nvt_cache_retry () /** * @brief Update the NVT cache in a child process. * + * @param[out] child_pid_out Optional output param for child PID. + * * @return 0 success, 1 update in progress, -1 error. Always exits with * EXIT_SUCCESS in child. */ static int -fork_update_nvt_cache () +fork_update_nvt_cache (pid_t *child_pid_out) { int pid; sigset_t sigmask_all, sigmask_current; @@ -1210,6 +1212,8 @@ fork_update_nvt_cache () } pid = fork_with_handlers (); + if (child_pid_out) + *child_pid_out = pid; switch (pid) { case 0: diff --git a/src/manage.c b/src/manage.c index b239b0649..12ae1c6a0 100644 --- a/src/manage.c +++ b/src/manage.c @@ -5064,7 +5064,7 @@ feed_sync_required () */ void manage_sync (sigset_t *sigmask_current, - int (*fork_update_nvt_cache) (), + int (*fork_update_nvt_cache) (pid_t*), gboolean try_gvmd_data_sync) { lockfile_t lockfile; @@ -5076,9 +5076,14 @@ manage_sync (sigset_t *sigmask_current, { if (feed_lockfile_lock (&lockfile) == 0) { - manage_sync_nvts (fork_update_nvt_cache); - manage_sync_scap (sigmask_current); - manage_sync_cert (sigmask_current); + pid_t nvts_pid, scap_pid, cert_pid; + nvts_pid = manage_sync_nvts (fork_update_nvt_cache); + scap_pid = manage_sync_scap (sigmask_current); + cert_pid = manage_sync_cert (sigmask_current); + + wait_for_pid (nvts_pid, "NVTs sync"); + wait_for_pid (scap_pid, "SCAP sync"); + wait_for_pid (cert_pid, "CERT sync"); lockfile_unlock (&lockfile); } diff --git a/src/manage.h b/src/manage.h index 4d5845e48..1dde1cfd0 100644 --- a/src/manage.h +++ b/src/manage.h @@ -2853,7 +2853,7 @@ void set_scheduled_user_uuid (const gchar* uuid); void -manage_sync (sigset_t *, int (*fork_update_nvt_cache) (), gboolean); +manage_sync (sigset_t *, int (*fork_update_nvt_cache) (pid_t*), gboolean); int manage_rebuild_gvmd_data_from_feed (const char *, diff --git a/src/manage_sql_nvts.c b/src/manage_sql_nvts.c index 052ec0dd1..95714193d 100644 --- a/src/manage_sql_nvts.c +++ b/src/manage_sql_nvts.c @@ -2390,11 +2390,15 @@ manage_update_nvt_cache_osp (const gchar *update_socket) * @brief Sync NVTs if newer NVTs are available. * * @param[in] fork_update_nvt_cache Function to do the update. + * + * @return PID of the forked process handling the VTs sync, -1 on error. */ -void -manage_sync_nvts (int (*fork_update_nvt_cache) ()) +pid_t +manage_sync_nvts (int (*fork_update_nvt_cache) (pid_t*)) { - fork_update_nvt_cache (); + pid_t child_pid = -1; + fork_update_nvt_cache (&child_pid); + return child_pid; } /** diff --git a/src/manage_sql_nvts.h b/src/manage_sql_nvts.h index 5e04edf83..e9db88fad 100644 --- a/src/manage_sql_nvts.h +++ b/src/manage_sql_nvts.h @@ -130,8 +130,8 @@ check_db_nvts (); int check_config_families (); -void -manage_sync_nvts (int (*) ()); +pid_t +manage_sync_nvts (int (*) (pid_t*)); int update_or_rebuild_nvts (int); diff --git a/src/manage_sql_secinfo.c b/src/manage_sql_secinfo.c index 25f1a6794..342c836f1 100644 --- a/src/manage_sql_secinfo.c +++ b/src/manage_sql_secinfo.c @@ -2999,8 +2999,10 @@ manage_db_reinit (const gchar *name) * @param[in] sigmask_current Sigmask to restore in child. * @param[in] update Function to do the sync. * @param[in] process_title Process title. + * + * @return PID of the forked process handling the SecInfo sync, -1 on error. */ -static void +static pid_t sync_secinfo (sigset_t *sigmask_current, int (*update) (void), const gchar *process_title) { @@ -3038,11 +3040,11 @@ sync_secinfo (sigset_t *sigmask_current, int (*update) (void), case -1: /* Parent on error. Reschedule and continue to next task. */ g_warning ("%s: fork failed", __func__); - return; + return -1; default: /* Parent. Continue to next task. */ - return; + return pid; } @@ -3439,13 +3441,15 @@ sync_cert () * @brief Sync the CERT DB. * * @param[in] sigmask_current Sigmask to restore in child. + * + * @return PID of the forked process handling the CERT sync, -1 on error. */ -void +pid_t manage_sync_cert (sigset_t *sigmask_current) { - sync_secinfo (sigmask_current, - sync_cert, - "Syncing CERT"); + return sync_secinfo (sigmask_current, + sync_cert, + "Syncing CERT"); } @@ -3921,13 +3925,15 @@ sync_scap () * @brief Sync the SCAP DB. * * @param[in] sigmask_current Sigmask to restore in child. + * + * @return PID of the forked process handling the SCAP sync, -1 on error. */ -void +pid_t manage_sync_scap (sigset_t *sigmask_current) { - sync_secinfo (sigmask_current, - sync_scap, - "Syncing SCAP"); + return sync_secinfo (sigmask_current, + sync_scap, + "Syncing SCAP"); } /** diff --git a/src/manage_sql_secinfo.h b/src/manage_sql_secinfo.h index d4ef087eb..7e7a83ed6 100644 --- a/src/manage_sql_secinfo.h +++ b/src/manage_sql_secinfo.h @@ -174,13 +174,13 @@ int secinfo_feed_version_status (); -void +pid_t manage_sync_scap (sigset_t *); int manage_rebuild_scap (GSList *, const db_conn_info_t *); -void +pid_t manage_sync_cert (sigset_t *); int diff --git a/src/utils.c b/src/utils.c index efe108b23..9c7ceb7cc 100644 --- a/src/utils.c +++ b/src/utils.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -906,3 +907,55 @@ fork_with_handlers () } return pid; } + +/** + * @brief Waits for a process with the given PID, retrying if interrupted. + * + * If the wait is interrupted or the process does not exist, only debug + * messages are logged. + * + * @param[in] pid The pid to wait for. + * @param[in] context Short context desciption for error and debug messages. + */ +void +wait_for_pid (pid_t pid, const char *context) +{ + gboolean retry = TRUE; + const char *shown_context = context ? context : "unknown context"; + if (pid <= 0) + { + g_message ("%s: No PID given (%s)", __func__, shown_context); + return; + } + + while (retry) + { + retry = FALSE; + pid_t ret = waitpid (pid, NULL, 0); + if (ret <= 0) + { + int err = errno; + if (errno == ECHILD) + { + g_debug ("%s: process with PID %d (%s) does not exist", + __func__, pid, shown_context); + } + else if (errno == EINTR) + { + g_debug ("%s: waitpid interrupted for PID %d (%s), retrying...", + __func__, pid, shown_context); + retry = TRUE; + } + else + { + g_warning ("%s: waitpid failed for PID %d (%s): %s", + __func__, pid, shown_context, strerror(err)); + } + } + else + { + g_debug ("%s: wait for PID %d (%s) successful", + __func__, pid, shown_context); + } + } +} diff --git a/src/utils.h b/src/utils.h index dfeed44b6..1054dc0ca 100644 --- a/src/utils.h +++ b/src/utils.h @@ -100,4 +100,7 @@ setup_signal_handler_info (int, void (*) (int, siginfo_t *, void *), int); int fork_with_handlers (); +void +wait_for_pid (pid_t, const char *); + #endif /* not _GVMD_UTILS_H */