check_signal: system call restart is done only once

Fujitsu: POSTK_TEMP_FIX_66
Refs: #1009
Change-Id: Ic0f04ac6b7f6c6bb01b55fb389bf9befd56b1dd9
This commit is contained in:
Tomoki Shirasawa
2018-09-05 13:59:10 +09:00
committed by Masamichi Takagi
parent c25fb2aa39
commit e4da71010c
12 changed files with 391 additions and 35 deletions

View File

@@ -0,0 +1,49 @@
diff --git a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c
index 4b2742b..a3173c9 100644
--- a/arch/x86_64/kernel/syscall.c
+++ b/arch/x86_64/kernel/syscall.c
@@ -1670,6 +1670,11 @@ long do_arch_prctl(unsigned long code, unsigned long address)
break;
case ARCH_SET_GS:
return -ENOTSUPP;
+ case 999: {
+ struct thread *thread = cpu_local_var(current);
+ thread->proc->dblsig = (int)address;
+ return 0;
+ }
default:
return -EINVAL;
}
diff --git a/kernel/include/process.h b/kernel/include/process.h
index 24acf1f..dd94469 100644
--- a/kernel/include/process.h
+++ b/kernel/include/process.h
@@ -580,6 +580,8 @@ struct process {
#endif // PROFILE_ENABLE
int nr_processes; /* For partitioned execution */
int process_rank; /* Rank in partition */
+
+ int dblsig;
};
/*
diff --git a/kernel/syscall.c b/kernel/syscall.c
index 15d4593..3d03fad 100644
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -9632,6 +9632,15 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
if (!list_empty(&thread->sigpending) ||
!list_empty(&thread->sigcommon->sigpending)) {
+ if (!list_empty(&thread->sigcommon->sigpending) &&
+ thread->proc->dblsig) {
+ kprintf("have a signal, waiting arrive more signal\n");
+ while (list_is_singular(
+ &thread->sigcommon->sigpending)) {
+ schedule();
+ }
+ kprintf("have some signals\n");
+ }
check_signal(l, NULL, num);
}

131
test/issues/1009/C1009.sh Normal file
View File

@@ -0,0 +1,131 @@
#!/bin/sh
BOOTPARAM="-c 1-7,17-23,9-15,25-31 -m 10G@0,10G@1"
USELTP=1
USEOSTEST=
################################################################################
BINDIR=
SBINDIR=
OSTESTDIR=
LTPDIR=
LTPBIN=
MCEXEC=
TESTMCK=
if [ -f $HOME/mck_test_config ]; then
. $HOME/mck_test_config
elif [ -f ../../../mck_test_config.sample ]; then
. ../../../mck_test_config.sample
else
BIN=
SBIN=
OSTEST=
LTP=
fi
#-------------------------------------------------------------------------------
if [ "x$BIN" = x ]; then
if [ -f ../../../config.h ]; then
str=`grep "^#define BINDIR " ../../../config.h | head -1 | sed 's/^#define BINDIR /BINDIR=/'`
eval $str
fi
else
BINDIR="$BIN"
fi
if [ "x$SBIN" = x ]; then
if [ -f ../../../Makefile ]; then
str=`grep ^SBINDIR ../../../Makefile | head -1 | sed 's/ //g'`
eval $str
fi
else
SBINDIR="$SBIN"
fi
if [ ! -x "$BINDIR/mcexec" ]; then
echo no mckernel found $BINDIR >&2
exit 1
fi
MCEXEC="$BINDIR/mcexec"
#-------------------------------------------------------------------------------
if [ "x$USELTP" != x ]; then
if [ "x$LTP" = x ]; then
if [ -f "$HOME/ltp/testcases/bin/fork01" ]; then
LTPDIR="$HOME/ltp"
fi
else
LTPDIR="$LTP"
fi
if [ ! -x "$LTPDIR/testcases/bin/fork01" ]; then
echo no LTP found $LTPDIR >&2
exit 1
fi
LTPBIN="$LTPDIR/testcases/bin"
fi
#-------------------------------------------------------------------------------
if [ "x$USEOSTEST" != x ]; then
if [ "x$OSTEST" = x ]; then
if [ -f "$HOME/ostest/bin/test_mck" ]; then
OSTESTDIR="$HOME/ostest"
fi
else
OSTESTDIR="$OSTEST"
fi
if [ ! -x "$OSTESTDIR"/bin/test_mck ]; then
echo no ostest found $OSTESTDIR >&2
exit 1
fi
TESTMCK="$OSTESTDIR/bin/test_mck"
fi
#===============================================================================
if [ ! -x "$SBINDIR/mcstop+release.sh" ]; then
echo mcstop+release: not found >&2
exit 1
fi
echo -n "mcstop+release.sh ... "
sudo "$SBINDIR/mcstop+release.sh"
echo "done"
if lsmod | grep mcctrl > /dev/null 2>&1; then
echo mckernel shutdown failed >&2
exit 1
fi
if [ ! -x "$SBINDIR/mcreboot.sh" ]; then
echo mcreboot: not found >&2
exit 1
fi
echo -n "mcreboot.sh $BOOTPARAM ... "
sudo "$SBINDIR/mcreboot.sh" $BOOTPARAM
echo "done"
if ! lsmod | grep mcctrl > /dev/null 2>&1; then
echo mckernel boot failed >&2
exit 1
fi
################################################################################
$MCEXEC ./C1009T01
if [ x$LTPDIR = x ]; then
echo no LTP found >&2
exit 1
fi
for i in kill01:02 kill12:03 pause02:04 sigaction01:05 ; do
tp=`echo $i|sed 's/:.*//'`
id=`echo $i|sed 's/.*://'`
$MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt
ok=`grep TPASS $tp.txt | wc -l`
ng=`grep TFAIL $tp.txt | wc -l`
if [ $ng = 0 ]; then
echo "*** C1009T$id: $tp OK ($ok)"
else
echo "*** C1009T$id: $tp NG (ok=$ok ng=%ng)"
fi
done

View File

@@ -0,0 +1,24 @@
Script started on Mon Sep 10 15:12:28 2018
bash-4.2$ make test
gcc -g -Wall -o C1009T01 C1009T01.c
sh ./C1009.sh
SIGUSR2
SIGUSR1
read A OK
read B OK
*** C1009T01: OK
kill01 1 TPASS : received expected signal 9
*** C1009T02: kill01 OK (1)
kill12 1 TPASS : Test passed
*** C1009T03: kill12 OK (1)
pause02 1 TPASS : pause was interrupted correctly
*** C1009T04: pause02 OK (1)
sigaction01 1 TPASS : SA_RESETHAND did not cause SA_SIGINFO to be cleared
sigaction01 2 TPASS : SA_RESETHAND was masked when handler executed
sigaction01 3 TPASS : sig has been masked because sa_mask originally contained sig
sigaction01 4 TPASS : siginfo pointer non NULL
*** C1009T05: sigaction01 OK (4)
bash-4.2$ exit
exit
Script done on Mon Sep 10 15:12:54 2018

107
test/issues/1009/C1009T01.c Normal file
View File

@@ -0,0 +1,107 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <asm/prctl.h>
#include <sys/prctl.h>
int arch_prctl(int code, unsigned long *addr);
void
sigusr(int sig)
{
if (sig == SIGUSR1) {
printf("SIGUSR1\n");
}
else if (sig == SIGUSR2) {
printf("SIGUSR2\n");
}
else {
printf("other sig\n");
}
fflush(stdout);
}
int
main(int argc, char **argv)
{
struct sigaction act;
pid_t pid1 = 0;
pid_t pid2 = 0;
pid_t parent;
int pfd[2];
char ch;
int rc;
unsigned long val;
memset(&act, '\0', sizeof(act));
act.sa_handler = sigusr;
act.sa_flags = SA_RESTART;
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGUSR2, &act, NULL);
pipe(pfd);
parent = getpid();
val = 1;
if (arch_prctl(999, (unsigned long *)val) == -1) {
fprintf(stderr, "C1009T01 WARN: no mckernel patch detected.\n");
exit(1);
}
if ((pid1 = fork())) {
pid2 = fork();
}
if (!pid1 || !pid2) {
int sig;
close(pfd[0]);
if (pid1)
sig = SIGUSR2;
else
sig = SIGUSR1;
sleep(1);
kill(parent, sig);
if (pid1) {
sleep(2);
ch = 'B';
}
else {
sleep(1);
ch = 'A';
}
write(pfd[1], &ch, 1);
close(pfd[1]);
exit(0);
}
rc = read(pfd[0], &ch, 1);
if (rc != 1) {
printf("C1009T01 NG: read error rc=%d errno=%d\n", rc, errno);
exit(1);
}
if (ch != 'A') {
printf("C1009T01 NG: read BAD DATA ch=%c\n", ch);
exit(1);
}
val = 0;
arch_prctl(999, (unsigned long *)val);
printf("read %c OK\n", ch);
rc = read(pfd[0], &ch, 1);
if (rc != 1) {
printf("C1009T01 NG: read error rc=%d errno=%d\n", rc, errno);
exit(1);
}
if (ch != 'B') {
printf("C1009T01 NG: read BAD DATA ch=%c\n", ch);
exit(1);
}
printf("read %c OK\n", ch);
printf("*** C1009T01: OK\n");
exit(0);
}

13
test/issues/1009/Makefile Normal file
View File

@@ -0,0 +1,13 @@
CC = gcc
TARGET = C1009T01
all:: $(TARGET)
C1009T01: C1009T01.c
$(CC) -g -Wall -o $@ $^
test:: all
sh ./C1009.sh
clean::
rm -f $(TARGET) *.o

27
test/issues/1009/README Normal file
View File

@@ -0,0 +1,27 @@
【Issue#1009 動作確認】
□ テスト内容
1. システムコール処理中にシグナルハンドラを呼び出す複数のシグナルを
受信し、当該システムコールを再処理するとき、当該システムコールが
1度しか処理されないことを確認する(指摘現象)。
尚、シグナルを同時に発行する状態を再現させるのが困難なため、本
テストは複数シグナルを待ち合わせるパッチを適用したカーネルで行う。
McKernel へのパッチファイルは C1009.patch である。
C1009T01 シグナルを複数受信したとき、システムコールの再処理を1度だけ行う確認
2. 変更が他のシグナル処理に影響しないことをLTPを用いて確認する。
C1009T02 kill01: kill の基本機能の確認
C1009T03 kill12: kill, wait, signal の組み合わせ確認
C1009T04 pause02: pause の基本機能の確認
C1009T05 sigaction01: sigaction の基本機能の確認
□ 実行手順
$ make test
実行できない場合は、C1009.shの以下の行を適切に書き換えた後に実行。
BIN= mcexec が存在するパス
SBIN= mcreboot.sh が存在するパス
LTP= LTP が存在するパス
□ 実行結果
C1009.txt 参照。
全ての項目が OK となっていることを確認。