summaryrefslogtreecommitdiff
path: root/source4/torture/smb2
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2017-11-15 10:12:06 -0800
committerJeremy Allison <jra@samba.org>2017-11-16 22:27:06 +0100
commit6c0d053ec0ea54e4152878564c5d21dfae9f346b (patch)
tree4e87d952f3b19d62cdc8088f88e966331e8d90f3 /source4/torture/smb2
parentf8cd211acc3824e01d89a6f8b6666c39aa5cd54e (diff)
downloadsamba-6c0d053ec0ea54e4152878564c5d21dfae9f346b.tar.gz
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
Diffstat (limited to 'source4/torture/smb2')
-rw-r--r--source4/torture/smb2/oplock.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/source4/torture/smb2/oplock.c b/source4/torture/smb2/oplock.c
index 1830a017e83..b6d9f842336 100644
--- a/source4/torture/smb2/oplock.c
+++ b/source4/torture/smb2/oplock.c
@@ -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);