Commit 50a20dfb authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

zdtm: fix race in test_waitsig for multithreaded tests

A signal can be handled by non-leader thread and sigsuspend
will not be woken up.

kill can send signals to a specified thread, so a futex is used for
synchronization.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 38c699a7
......@@ -2,6 +2,7 @@ include ../Makefile.inc
CFLAGS = -g -O2 -Wall -Werror -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
LIBDIR = .
LIB = libzdtmtst.a
LIBSRC = datagen.c msg.c parseargs.c test.c streamutil.c lock.c ns.c tcp.c
......
#ifndef CR_LOCK_H_
#define CR_LOCK_H_
#include <stdint.h>
#include <linux/futex.h>
#include <linux/unistd.h>
#include <sys/time.h>
......
......@@ -103,7 +103,7 @@ static void ns_sig_hand(int signo)
char buf[128] = "";
if (signo == SIGTERM) {
sig_received = signo;
futex_set_and_wake(&sig_received, signo);
len = snprintf(buf, sizeof(buf), "Time to stop and check\n");
goto write_out;
}
......@@ -114,9 +114,9 @@ static void ns_sig_hand(int signo)
return;
if (pid == -1) {
if (errno == ECHILD) {
if (sig_received)
if (futex_get(&sig_received))
return;
sig_received = signo;
futex_set_and_wake(&sig_received, signo);
len = snprintf(buf, sizeof(buf),
"All test processes exited\n");
} else {
......
#ifndef __ZDTM_NS__
#define __ZDTM_NS__
extern volatile sig_atomic_t sig_received;
#include "lock.h"
extern futex_t sig_received;
extern char *pidfile;
extern void ns_create(int argc, char **argv);
......
......@@ -15,13 +15,14 @@
#include <string.h>
#include "zdtmtst.h"
#include "lock.h"
#include "ns.h"
volatile sig_atomic_t sig_received = 0;
futex_t sig_received;
static void sig_hand(int signo)
{
sig_received = signo;
futex_set_and_wake(&sig_received, signo);
}
static char *outfile;
......@@ -153,7 +154,7 @@ void test_init(int argc, char **argv)
if (pid) { /* parent will exit when the child is ready */
test_waitsig();
if (sig_received == SIGCHLD) {
if (futex_get(&sig_received) == SIGCHLD) {
int ret;
waitpid(pid, &ret, 0);
......@@ -290,7 +291,7 @@ void test_init_ns(int argc, char **argv, unsigned long clone_flags,
/* parent will exit when the child is ready */
test_waitsig();
if (sig_received == SIGCHLD) {
if (futex_get(&sig_received) == SIGCHLD) {
int ret;
waitpid(pid, &ret, 0);
......@@ -330,21 +331,10 @@ out:
int test_go(void)
{
return !sig_received;
return !futex_get(&sig_received);
}
void test_waitsig(void)
{
sigset_t mask, oldmask;
/* Set up the mask of signals to temporarily block. */
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGCHLD);
/* Wait for a signal to arrive. */
sigprocmask(SIG_BLOCK, &mask, &oldmask);
while (!sig_received)
sigsuspend (&oldmask);
sigprocmask (SIG_UNBLOCK, &mask, NULL);
futex_wait_while(&sig_received, 0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment