got_break = 1;
}
+static int got_alarm;
+
+/*
+ * Signal handler.
+ */
+
+static void got_alarm_fn(int sig)
+{
+ got_alarm = 1;
+}
+
/*
* Child process function.
*/
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) {
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);
}
#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.
*/
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;
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,
"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);