1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-23 09:57:40 +03:00

s4:torture: fix multi_smb_test child status tracking.

The original code in torture_start_procs() lost status of
child status. So the affected test caseses
(defer_open, ntdeny1, bench-torture, and also direct
 torture_start_proxy-user bench-nbench) were not always
able to correctly detect and treat errors in the worker children.

With this patch, torture_create_procs() correctly puts
child result and reason into top level torture_result(),
thereby in particular fixing remaining unexpected errors
in the flapping deferopen test.

Signed-off-by: Michael Adam <obnox@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>

Autobuild-User(master): Michael Adam <obnox@samba.org>
Autobuild-Date(master): Wed Sep 10 13:15:17 CEST 2014 on sn-devel-104
This commit is contained in:
Michael Adam 2014-08-21 10:32:00 +02:00
parent 589344802d
commit 868e8f42a0

View File

@ -582,12 +582,19 @@ static void sigcont(int sig)
{
}
double torture_create_procs(struct torture_context *tctx,
bool (*fn)(struct torture_context *, struct smbcli_state *, int), bool *result)
struct child_status {
pid_t pid;
bool start;
enum torture_result result;
char reason[1024];
};
double torture_create_procs(struct torture_context *tctx,
bool (*fn)(struct torture_context *, struct smbcli_state *, int),
bool *result)
{
int i, status;
volatile pid_t *child_status;
volatile bool *child_status_out;
struct child_status *child_status;
int synccount;
int tries = 8;
int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
@ -600,21 +607,15 @@ double torture_create_procs(struct torture_context *tctx,
signal(SIGCONT, sigcont);
child_status = (volatile pid_t *)anonymous_shared_allocate(sizeof(pid_t)*torture_nprocs);
if (!child_status) {
child_status = (struct child_status *)anonymous_shared_allocate(
sizeof(struct child_status)*torture_nprocs);
if (child_status == NULL) {
printf("Failed to setup shared memory\n");
return -1;
}
child_status_out = (volatile bool *)anonymous_shared_allocate(sizeof(bool)*torture_nprocs);
if (!child_status_out) {
printf("Failed to setup result status shared memory\n");
return -1;
}
for (i = 0; i < torture_nprocs; i++) {
child_status[i] = 0;
child_status_out[i] = true;
ZERO_STRUCT(child_status[i]);
}
tv = timeval_current();
@ -623,6 +624,7 @@ double torture_create_procs(struct torture_context *tctx,
procnum = i;
if (fork() == 0) {
char *myname;
bool ok;
pid_t mypid = getpid();
srandom(((int)mypid) ^ ((int)time(NULL)));
@ -646,17 +648,45 @@ double torture_create_procs(struct torture_context *tctx,
smb_msleep(100);
}
child_status[i] = getpid();
child_status[i].pid = getpid();
pause();
if (child_status[i]) {
if (!child_status[i].start) {
child_status[i].result = TORTURE_ERROR;
printf("Child %d failed to start!\n", i);
child_status_out[i] = 1;
_exit(1);
}
child_status_out[i] = fn(tctx, current_cli, i);
ok = fn(tctx, current_cli, i);
if (!ok) {
if (tctx->last_result == TORTURE_OK) {
torture_result(tctx, TORTURE_ERROR,
"unknown error: missing "
"torture_result call?\n");
}
child_status[i].result = tctx->last_result;
if (strlen(tctx->last_reason) > 1023) {
/* note: reason already contains \n */
torture_comment(tctx,
"child %d (pid %u) failed: %s",
i,
(unsigned)child_status[i].pid,
tctx->last_reason);
}
snprintf(child_status[i].reason,
1024, "child %d (pid %u) failed: %s",
i, (unsigned)child_status[i].pid,
tctx->last_reason);
/* ensure proper "\n\0" termination: */
if (child_status[i].reason[1022] != '\0') {
child_status[i].reason[1022] = '\n';
child_status[i].reason[1023] = '\0';
}
}
_exit(0);
}
}
@ -664,9 +694,13 @@ double torture_create_procs(struct torture_context *tctx,
do {
synccount = 0;
for (i=0;i<torture_nprocs;i++) {
if (child_status[i]) synccount++;
if (child_status[i].pid != 0) {
synccount++;
}
}
if (synccount == torture_nprocs) {
break;
}
if (synccount == torture_nprocs) break;
smb_msleep(100);
} while (timeval_elapsed(&tv) < start_time_limit);
@ -675,8 +709,8 @@ double torture_create_procs(struct torture_context *tctx,
/* cleanup child processes */
for (i = 0; i < torture_nprocs; i++) {
if (child_status[i]) {
kill(child_status[i], SIGTERM);
if (child_status[i].pid != 0) {
kill(child_status[i].pid, SIGTERM);
}
}
@ -689,7 +723,7 @@ double torture_create_procs(struct torture_context *tctx,
/* start the client load */
tv = timeval_current();
for (i=0;i<torture_nprocs;i++) {
child_status[i] = 0;
child_status[i].start = true;
}
printf("%d clients started\n", torture_nprocs);
@ -705,12 +739,15 @@ double torture_create_procs(struct torture_context *tctx,
}
printf("\n");
for (i=0;i<torture_nprocs;i++) {
if (!child_status_out[i]) {
if (child_status[i].result != TORTURE_OK) {
*result = false;
torture_result(tctx, child_status[i].result,
"%s", child_status[i].reason);
}
}
return timeval_elapsed(&tv);
}