1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-26 21:57:41 +03:00

s4: torture: Ensure kernel oplock test can't hang in pause().

Use an alarm to break out of waiting for a signal.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13121

Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>

Autobuild-User(master): Jeremy Allison <jra@samba.org>
Autobuild-Date(master): Thu Nov 16 22:27:06 CET 2017 on sn-devel-144
This commit is contained in:
Jeremy Allison 2017-11-15 10:12:06 -08:00
parent f8cd211acc
commit 6c0d053ec0

View File

@ -4817,6 +4817,17 @@ static void got_rt_break(int sig)
got_break = 1;
}
static int got_alarm;
/*
* Signal handler.
*/
static void got_alarm_fn(int sig)
{
got_alarm = 1;
}
/*
* Child process function.
*/
@ -4835,6 +4846,13 @@ static int do_child_process(int pipefd, const char *name)
if (ret == -1) {
return 1;
}
/* Set up a signal handler for SIGALRM. */
ZERO_STRUCT(act);
act.sa_handler = got_alarm_fn;
ret = sigaction(SIGALRM, &act, NULL);
if (ret == -1) {
return 1;
}
/* Open the passed in file and get a kernel oplock. */
fd = open(name, O_RDWR, 0666);
if (fd == -1) {
@ -4857,16 +4875,26 @@ static int do_child_process(int pipefd, const char *name)
return 5;
}
/* Ensure the pause doesn't hang forever. */
alarm(5);
/* Wait for RT_SIGNAL_LEASE. */
ret = pause();
if (ret != -1 || errno != EINTR) {
return 6;
}
if (got_alarm == 1) {
return 10;
}
if (got_break != 1) {
return 7;
}
/* Cancel any pending alarm. */
alarm(0);
/* Force the server to wait for 3 seconds. */
sleep(3);
@ -4928,6 +4956,23 @@ static bool wait_for_child_oplock(struct torture_context *tctx,
}
#endif
static void child_sig_term_handler(struct tevent_context *ev,
struct tevent_signal *se,
int signum,
int count,
void *siginfo,
void *private_data)
{
int *pstatus = (int *)private_data;
int status;
wait(&status);
if (WIFEXITED(status)) {
*pstatus = WEXITSTATUS(status);
} else {
*pstatus = status;
}
}
/*
* Deal with a non-smbd process holding a kernel oplock.
*/
@ -4944,6 +4989,8 @@ static bool test_smb2_kernel_oplocks8(struct torture_context *tctx,
struct smb2_handle h1 = {{0}};
struct smb2_handle h2 = {{0}};
const char *localdir = torture_setting_string(tctx, "localdir", NULL);
struct tevent_signal *se = NULL;
int child_exit_code = -1;
time_t start;
time_t end;
@ -4963,6 +5010,14 @@ static bool test_smb2_kernel_oplocks8(struct torture_context *tctx,
smb2_util_close(tree, h1);
ZERO_STRUCT(h1);
se = tevent_add_signal(tctx->ev,
tctx,
SIGCHLD,
0,
child_sig_term_handler,
&child_exit_code);
torture_assert(tctx, se != NULL, "tevent_add_signal failed\n");
/* Take the oplock locally in a sub-process. */
ret = wait_for_child_oplock(tctx, localdir, fname);
torture_assert_goto(tctx, ret = true, ret, done,
@ -5013,6 +5068,18 @@ static bool test_smb2_kernel_oplocks8(struct torture_context *tctx,
"Error opening the file\n");
h2 = io.out.file.handle;
/* Wait for the exit code from the child. */
while (child_exit_code == -1) {
int rval = tevent_loop_once(tctx->ev);
torture_assert(tctx, rval == 0, "tevent_loop_once error\n");
}
if (child_exit_code != 0) {
torture_comment(tctx, "Bad child exit code %d\n",
child_exit_code);
ret = false;
}
done:
if (!smb2_util_handle_empty(h1)) {
smb2_util_close(tree, h1);