test-async: Wait for asynchronous_sync() to finish (#36611)
Otherwise, if the system is busy, TEST-02-UNITTESTS will fail as systemd will time out trying to kill the transient unit that we're running test-async in.
This commit is contained in:
+10
-8
@@ -14,7 +14,7 @@
|
||||
#include "process-util.h"
|
||||
#include "signal-util.h"
|
||||
|
||||
int asynchronous_sync(pid_t *ret_pid) {
|
||||
int asynchronous_sync(PidRef *ret_pid) {
|
||||
int r;
|
||||
|
||||
/* This forks off an invocation of fork() as a child process, in order to initiate synchronization to
|
||||
@@ -22,7 +22,7 @@ int asynchronous_sync(pid_t *ret_pid) {
|
||||
* original process ever, and a thread would do that as the process can't exit with threads hanging in blocking
|
||||
* syscalls. */
|
||||
|
||||
r = safe_fork("(sd-sync)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|(ret_pid ? 0 : FORK_DETACH), ret_pid);
|
||||
r = pidref_safe_fork("(sd-sync)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|(ret_pid ? 0 : FORK_DETACH), ret_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
@@ -34,17 +34,19 @@ int asynchronous_sync(pid_t *ret_pid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int asynchronous_fsync(int fd, pid_t *ret_pid) {
|
||||
int asynchronous_fsync(int fd, PidRef *ret_pid) {
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
/* Same as asynchronous_sync() above, but calls fsync() on a specific fd */
|
||||
|
||||
r = safe_fork_full("(sd-fsync)",
|
||||
/* stdio_fds= */ NULL,
|
||||
/* except_fds= */ &fd,
|
||||
/* n_except_fds= */ 1,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|(ret_pid ? 0 : FORK_DETACH), ret_pid);
|
||||
r = pidref_safe_fork_full(
|
||||
"(sd-fsync)",
|
||||
/* stdio_fds= */ NULL,
|
||||
/* except_fds= */ &fd,
|
||||
/* n_except_fds= */ 1,
|
||||
FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|(ret_pid ? 0 : FORK_DETACH),
|
||||
ret_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
||||
+3
-2
@@ -4,6 +4,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "macro.h"
|
||||
#include "pidref.h"
|
||||
#include "rm-rf.h"
|
||||
|
||||
/* These functions implement various potentially slow operations that are executed asynchronously. They are
|
||||
@@ -19,8 +20,8 @@
|
||||
* child, or never use clone()/clone3() and stick to fork() only. Because we need clone()/clone3() we opted
|
||||
* for avoiding threads. */
|
||||
|
||||
int asynchronous_sync(pid_t *ret_pid);
|
||||
int asynchronous_fsync(int fd, pid_t *ret_pid);
|
||||
int asynchronous_sync(PidRef *ret_pid);
|
||||
int asynchronous_fsync(int fd, PidRef *ret_pid);
|
||||
|
||||
int asynchronous_close(int fd);
|
||||
void asynchronous_close_many(const int fds[], size_t n_fds);
|
||||
|
||||
@@ -226,7 +226,7 @@ int sync_with_progress(int fd) {
|
||||
unsigned long long dirty = ULLONG_MAX;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
const char *what;
|
||||
pid_t pid;
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
int r;
|
||||
|
||||
BLOCK_SIGNALS(SIGCHLD);
|
||||
@@ -235,13 +235,13 @@ int sync_with_progress(int fd) {
|
||||
* the progress. If the timeout lapses, the assumption is that the particular sync stalled. */
|
||||
|
||||
if (fd >= 0) {
|
||||
r = asynchronous_fsync(fd, &pid);
|
||||
r = asynchronous_fsync(fd, &pidref);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to fork fsync(): %m");
|
||||
|
||||
(void) fd_get_path(fd, &path);
|
||||
} else {
|
||||
r = asynchronous_sync(&pid);
|
||||
r = asynchronous_sync(&pidref);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to fork sync(): %m");
|
||||
}
|
||||
@@ -253,7 +253,7 @@ int sync_with_progress(int fd) {
|
||||
* SYNC_PROGRESS_ATTEMPTS lapse without progress being made,
|
||||
* we assume that the sync is stalled */
|
||||
for (unsigned checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) {
|
||||
r = wait_for_terminate_with_timeout(pid, SYNC_TIMEOUT_USEC);
|
||||
r = wait_for_terminate_with_timeout(pidref.pid, SYNC_TIMEOUT_USEC);
|
||||
if (r == 0)
|
||||
/* Sync finished without error (sync() call itself does not return an error code) */
|
||||
return 0;
|
||||
@@ -267,8 +267,8 @@ int sync_with_progress(int fd) {
|
||||
|
||||
/* Only reached in the event of a timeout. We should issue a kill to the stray process. */
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(ETIMEDOUT),
|
||||
"Syncing %s - timed out, issuing SIGKILL to PID "PID_FMT".", what, pid);
|
||||
(void) kill(pid, SIGKILL);
|
||||
"Syncing %s - timed out, issuing SIGKILL to PID "PID_FMT".", what, pidref.pid);
|
||||
(void) pidref_kill(&pidref, SIGKILL);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
TEST(asynchronous_sync) {
|
||||
ASSERT_OK(asynchronous_sync(NULL));
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
ASSERT_OK(asynchronous_sync(&pidref));
|
||||
ASSERT_OK(pidref_wait_for_terminate(&pidref, /* ret= */ NULL));
|
||||
}
|
||||
|
||||
static void wait_fd_closed(int fd) {
|
||||
|
||||
Reference in New Issue
Block a user