Merge branch 'dyn-tests' into 'master'
Use dynamic link and add more tests See merge request redox-os/relibc!814
This commit is contained in:
+1
-2
@@ -58,8 +58,7 @@ test:x86_64:
|
||||
stage: test
|
||||
needs: [x86_64]
|
||||
script:
|
||||
# TODO: sigaction and sigaltstack hangs with multi core
|
||||
- REDOXER_QEMU_ARGS="-smp 1" ./check.sh --arch=x86_64 --test
|
||||
- ./check.sh --arch=x86_64 --test
|
||||
|
||||
test:aarch64:
|
||||
stage: test
|
||||
|
||||
@@ -114,7 +114,6 @@ test: sysroot/$(TARGET)
|
||||
# TODO: Fix SIGILL when running cargo test
|
||||
# $(CARGO_TEST) test
|
||||
$(MAKE) -C tests run
|
||||
$(MAKE) -C tests verify
|
||||
|
||||
|
||||
$(BUILD)/$(PROFILE)/libc.so: $(BUILD)/$(PROFILE)/librelibc.a $(BUILD)/openlibm/libopenlibm.a
|
||||
|
||||
@@ -98,8 +98,8 @@ run_redoxer() {
|
||||
redoxer toolchain || { echo -e "${RED}Fail: redoxer toolchain for: $target.${NC}" && exit 1; }
|
||||
export CARGOFLAGS=""
|
||||
export CARGO_TEST="redoxer"
|
||||
export TEST_RUNNER="redoxer exec --folder . --"
|
||||
MAKE_ACTION="$MAKE_ACTION SKIP_REDOX=1"
|
||||
export TEST_RUNNER="redoxer exec --folder ../sysroot/$TARGET:/usr --folder . --"
|
||||
MAKE_ACTION="$MAKE_ACTION IS_REDOX=1"
|
||||
else
|
||||
REDOXER_ENV=""
|
||||
fi
|
||||
|
||||
+41
-50
@@ -1,16 +1,19 @@
|
||||
include ../config.mk
|
||||
|
||||
SKIP_REDOX?=0
|
||||
IS_REDOX?=0
|
||||
|
||||
# If compiling for Redox, SKIP_REDOX must be 1
|
||||
ifeq ($(SKIP_REDOX),1)
|
||||
REDOX_FAILING_TESTS=
|
||||
# If compiling for Redox, IS_REDOX must be 1
|
||||
ifeq ($(IS_REDOX),1)
|
||||
FAILING_TESTS=signals/killpg-child
|
||||
else
|
||||
REDOX_FAILING_TESTS=tls \
|
||||
FAILING_TESTS=tls \
|
||||
futimens \
|
||||
mkfifo \
|
||||
stdlib/ptsname \
|
||||
sys_mman
|
||||
sys_mman \
|
||||
# resource/getrusage
|
||||
# time/times
|
||||
# netdb/netdb
|
||||
|
||||
endif
|
||||
|
||||
@@ -178,10 +181,7 @@ EXPECT_NAMES=\
|
||||
wctype/towlower \
|
||||
wctype/towupper \
|
||||
mknod \
|
||||
mknodat \
|
||||
$(REDOX_FAILING_TESTS)
|
||||
# TODO: Fix this
|
||||
# netdb/netdb \
|
||||
mknodat
|
||||
|
||||
BUILD?=.
|
||||
|
||||
@@ -190,8 +190,7 @@ DYNAMIC_ONLY_NAMES=\
|
||||
dlopen_scopes
|
||||
|
||||
# Binaries that may generate varied output
|
||||
NAMES=\
|
||||
$(EXPECT_NAMES) \
|
||||
VARIED_NAMES=\
|
||||
dirent/main \
|
||||
dirent/posix_getdents \
|
||||
kill-waitpid \
|
||||
@@ -212,7 +211,6 @@ NAMES=\
|
||||
signals/killpg0-self \
|
||||
signals/kill-group \
|
||||
signals/kill-child \
|
||||
signals/killpg-child \
|
||||
signals/killpg-self \
|
||||
signals/pthread_kill-invalid \
|
||||
signals/pthread_kill-child \
|
||||
@@ -293,29 +291,31 @@ NAMES=\
|
||||
grp/gr_iter \
|
||||
waitpid \
|
||||
waitpid_multiple \
|
||||
sigqueue
|
||||
# resource/getrusage
|
||||
# time/times
|
||||
sigqueue \
|
||||
$(FAILING_TESTS)
|
||||
|
||||
# Tests run with `expect` (require a .c file and an .exp file
|
||||
# that takes the produced binary as the first argument)
|
||||
EXPECT_INPUT_NAMES=\
|
||||
unistd/getpass
|
||||
|
||||
# TODO: Dynamic linking is currently broken on Redox
|
||||
# TODO: Some tests in NAMES break the kernel
|
||||
ifeq ($(SKIP_REDOX),0)
|
||||
BINS=$(patsubst %,$(BUILD)/bins_static/%,$(NAMES))
|
||||
BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(NAMES))
|
||||
BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(DYNAMIC_ONLY_NAMES))
|
||||
# TODO: Dynamic linking doesn't work with NATIVE_RELIBC=0
|
||||
# TODO: Reduce bins_static tests, only execute it when static link difference matters
|
||||
ifeq ($(IS_REDOX),0)
|
||||
BINS+=$(patsubst %,$(BUILD)/bins_static/%,$(VARIED_NAMES))
|
||||
BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(VARIED_NAMES))
|
||||
EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_static/%,$(EXPECT_NAMES))
|
||||
EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(EXPECT_NAMES))
|
||||
EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(DYNAMIC_ONLY_NAMES))
|
||||
EXPECT_INPUT_BINS=$(patsubst %,$(BUILD)/bins_expect_input/%,$(EXPECT_INPUT_NAMES))
|
||||
else
|
||||
# TODO: Not compiling static tests, too heavy for redoxerd
|
||||
BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(VARIED_NAMES))
|
||||
EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(EXPECT_NAMES))
|
||||
EXPECT_BINS+=$(patsubst %,$(BUILD)/bins_dynamic/%,$(DYNAMIC_ONLY_NAMES))
|
||||
# TODO: EXPECT_INPUT_BINS
|
||||
endif
|
||||
|
||||
EXPECT_BINS=$(patsubst %,$(BUILD)/bins_static/%,$(EXPECT_NAMES))
|
||||
|
||||
|
||||
CARGO_TEST?=cargo
|
||||
TEST_RUNNER?=
|
||||
|
||||
@@ -326,35 +326,18 @@ all: $(BINS)
|
||||
clean:
|
||||
rm -rf bins_* gen *.out
|
||||
|
||||
run: | $(BINS) $(EXPECT_INPUT_BINS)
|
||||
run: bins_verify/relibc-tests $(BINS) $(EXPECT_BINS) $(EXPECT_INPUT_BINS)
|
||||
@echo "\033[1;36;49mRunning tests\033[0m"
|
||||
@for bin in $(BINS); \
|
||||
do \
|
||||
echo "\033[0;96;49m# $${bin} #\033[0m"; \
|
||||
${TEST_RUNNER} "$${bin}" test args || exit $$?; \
|
||||
done
|
||||
$(TEST_RUNNER) $< $(patsubst %,-s%,$(BINS)) $(EXPECT_BINS)
|
||||
for exp in $(EXPECT_INPUT_BINS); \
|
||||
do \
|
||||
echo "# expect $$(readlink -e $${exp}.exp) $$(readlink -e $${exp}) #"; \
|
||||
expect "$$(readlink -e $${exp}.exp)" "$$(readlink -e $${exp})" test args || exit $$?; \
|
||||
done
|
||||
|
||||
expected: | $(EXPECT_BINS)
|
||||
rm -rf expected
|
||||
mkdir -p expected
|
||||
for bin in $(EXPECT_BINS); \
|
||||
do \
|
||||
echo "# $${bin} #"; \
|
||||
mkdir -p expected/`dirname $${bin}`; \
|
||||
"$${bin}" test args > "expected/$${bin}.stdout" 2> "expected/$${bin}.stderr" || exit $$?; \
|
||||
done
|
||||
|
||||
bins_verify/relibc-tests: src/main.rs
|
||||
$(CARGO_TEST) build --release --bin relibc-tests --out-dir bins_verify -Z unstable-options
|
||||
|
||||
verify: bins_verify/relibc-tests | $(EXPECT_BINS)
|
||||
$(TEST_RUNNER) $< $(EXPECT_BINS)
|
||||
|
||||
FLAGS=\
|
||||
-std=c11 \
|
||||
-fno-builtin \
|
||||
@@ -375,6 +358,7 @@ DYNAMIC_FLAGS=\
|
||||
-Wl,-export-dynamic
|
||||
|
||||
SYSROOT?=$(abspath ../sysroot/$(TARGET)/)
|
||||
SYSROOT_TARGET?=$(SYSROOT)
|
||||
|
||||
$(SYSROOT):
|
||||
$(MAKE) -C .. sysroot
|
||||
@@ -389,17 +373,24 @@ FLAGS+=\
|
||||
$(SYSROOT)/lib/crti.o \
|
||||
$(SYSROOT)/lib/crtn.o
|
||||
|
||||
SYSROOT_LIB=$(shell realpath ../sysroot/$(TARGET)/lib/)
|
||||
|
||||
STATIC_FLAGS+=\
|
||||
$(SYSROOT_LIB)/libc.a
|
||||
$(SYSROOT)/lib/libc.a
|
||||
|
||||
ifeq ($(IS_REDOX),0)
|
||||
DYNAMIC_FLAGS+=\
|
||||
-Wl,-dynamic-linker=$(SYSROOT)/$(LD_SO_PATH) \
|
||||
-Wl,-rpath=$(SYSROOT_LIB):\$$ORIGIN \
|
||||
-L $(SYSROOT_LIB) \
|
||||
-Wl,-dynamic-linker=$(SYSROOT_TARGET)/$(LD_SO_PATH) \
|
||||
-Wl,-rpath=$(SYSROOT_TARGET)/lib:\$$ORIGIN \
|
||||
-L $(SYSROOT)/lib \
|
||||
-lc \
|
||||
-fpic
|
||||
else
|
||||
# TODO: Make -dynamic-linker works
|
||||
DYNAMIC_FLAGS+=\
|
||||
-Wl,-rpath=$(SYSROOT_TARGET)/lib:\$$ORIGIN \
|
||||
-L $(SYSROOT)/lib \
|
||||
-lc \
|
||||
-fpic
|
||||
endif
|
||||
|
||||
DEPS=../sysroot/$(TARGET)
|
||||
else
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
void *routine(void *arg) {
|
||||
assert(arg == NULL);
|
||||
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
puts("Thread succeeded");
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ struct arg2 {
|
||||
void *routine1(void *arg) {
|
||||
assert(arg == NULL);
|
||||
puts("Thread 1 spawned, waiting 1s.");
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
puts("Thread 1 finished.");
|
||||
return strdup("message from thread 1");
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ int main(void) {
|
||||
int status;
|
||||
|
||||
puts("Start, sleeping 1 second");
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
pthread_t thread;
|
||||
void *arg = NULL;
|
||||
if ((status = pthread_create(&thread, NULL, thread_main, arg)) != 0) {
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ int main() {
|
||||
if (pid == 0) {
|
||||
// Test behavior on Redox when TRACEME hasn't been activated
|
||||
// before waitpid is invoked!
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
int result = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
|
||||
ERROR_IF(ptrace, result, == -1);
|
||||
|
||||
@@ -36,8 +36,8 @@ void child_proc(int signum)
|
||||
sigemptyset(&act.sa_mask);
|
||||
sigaction(signum, &act, NULL);
|
||||
|
||||
status = sleep(10);
|
||||
ERROR_IF(sleep, status, == 0);
|
||||
status = usleep(200);
|
||||
ERROR_IF(usleep, status, == 0);
|
||||
|
||||
assert(sig_handled != 0);
|
||||
|
||||
@@ -48,7 +48,7 @@ void parent(int signum, pid_t pid)
|
||||
{
|
||||
int status;
|
||||
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
status = kill(pid, signum);
|
||||
ERROR_IF(kill, status, != 0);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ int killpg_test2(int signum)
|
||||
int i;
|
||||
sigignore(signum);
|
||||
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
child_pgid = getpgid(child_pid);
|
||||
ERROR_IF(getpgid, child_pgid, == -1);
|
||||
|
||||
@@ -36,7 +36,7 @@ int main()
|
||||
// Now the child_thread exited, it is an invalid tid
|
||||
memcpy(&invalid_tid, &child_thread,
|
||||
sizeof(pthread_t));
|
||||
sleep(3);
|
||||
usleep(300);
|
||||
|
||||
int status;
|
||||
status = pthread_kill(invalid_tid, 0);
|
||||
|
||||
@@ -38,7 +38,7 @@ void *a_thread_func( void *arg)
|
||||
sem1=INMAIN;
|
||||
|
||||
while(sem1==INMAIN)
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
// sleep(50);
|
||||
|
||||
@@ -61,16 +61,16 @@ int pthread_kill_test1(int signum)
|
||||
ERROR_IF(pthread_create, status, != 0);
|
||||
|
||||
while(sem1==INTHREAD)
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
status = pthread_kill(new_th, signum);
|
||||
ERROR_IF(pthread_kill, status, != 0);
|
||||
|
||||
sleep(2);
|
||||
usleep(200);
|
||||
sem1=INTHREAD;
|
||||
|
||||
while(handler_called==0)
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
ERROR_IF(pthread_kill, handler_called, == -1);
|
||||
ERROR_IF(pthread_kill, handler_called, == 0);
|
||||
|
||||
@@ -71,14 +71,14 @@ int sigpause_error(int signum){
|
||||
status = pthread_create(&new_th, NULL, d_thread_func, (void *)&signum);
|
||||
ERROR_IF(pthread_create, status, != 0);
|
||||
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
status = pthread_kill(new_th, signum);
|
||||
ERROR_IF(pthread_kill, status, != 0);
|
||||
|
||||
sem = INTHREAD;
|
||||
while (sem == INTHREAD)
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
if(result == 2) {
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
@@ -45,12 +45,12 @@ int sigpause_basic(int signum)
|
||||
status = pthread_create(&new_th, NULL, a_thread_func, (void *)&signum);
|
||||
ERROR_IF(pthread_create, status, != 0);
|
||||
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
status = pthread_kill(new_th, signum);
|
||||
ERROR_IF(pthread_kill, status, != 0);
|
||||
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
if (handler_called != 1){
|
||||
prinft("handler wasn't called\n");
|
||||
|
||||
@@ -77,7 +77,7 @@ int sigpause_revert(int signum) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
|
||||
if((status = pthread_kill(new_th, signum)) != 0)
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@ int sigpause_suspend(int signum)
|
||||
perror("failed to create thread");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
assert(!atomic_load(&completed));
|
||||
|
||||
if ((status = pthread_kill(new_th, signum)) != 0) {
|
||||
|
||||
+114
-12
@@ -1,8 +1,11 @@
|
||||
use std::{
|
||||
env, fs,
|
||||
io::{self, Write},
|
||||
io::{self, Read, Write},
|
||||
path::PathBuf,
|
||||
process::{self, Command, ExitStatus},
|
||||
process::{self, Command, ExitStatus, Stdio},
|
||||
sync::mpsc,
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
fn expected(bin: &str, kind: &str, generated: &[u8], status: ExitStatus) -> Result<(), String> {
|
||||
@@ -47,6 +50,8 @@ const STATUS_ONLY: &str = "-s";
|
||||
|
||||
fn main() {
|
||||
let mut failures = Vec::new();
|
||||
let timeout = Duration::from_secs(10);
|
||||
let slowtime = Duration::from_secs(1);
|
||||
|
||||
for bin in env::args().skip(1) {
|
||||
let status_only = bin.starts_with(STATUS_ONLY);
|
||||
@@ -58,30 +63,127 @@ fn main() {
|
||||
|
||||
println!("# {} #", bin);
|
||||
|
||||
match Command::new(&bin).arg("test").arg("args").output() {
|
||||
Ok(output) => {
|
||||
let start_time = Instant::now();
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let bin_for_spawn = bin.clone();
|
||||
|
||||
// There's an issue when pthread hangs, spawn() also hangs, so let's use separate thread to spawn
|
||||
thread::spawn(move || {
|
||||
let result = Command::new(&bin_for_spawn)
|
||||
.arg("test")
|
||||
.arg("args")
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn();
|
||||
tx.send(result).expect("Can't send");
|
||||
});
|
||||
|
||||
let mut status = None;
|
||||
let mut child = None;
|
||||
|
||||
loop {
|
||||
if start_time.elapsed() > timeout {
|
||||
let failure = format!(
|
||||
"\x1b[0;91;49m{}: assumed hangs after {}ms\x1b[0m",
|
||||
bin,
|
||||
start_time.elapsed().as_millis()
|
||||
);
|
||||
println!("{}", failure);
|
||||
failures.push(failure);
|
||||
break;
|
||||
}
|
||||
// A pretty rare hang on pthread/barrier which also stops this loop :(
|
||||
// https://gitlab.redox-os.org/redox-os/relibc/-/issues/238
|
||||
if &bin == "./bins_dynamic/pthread/barrier"
|
||||
|| &bin == "./bins_dynamic/pthread/once"
|
||||
|| start_time.elapsed() > slowtime
|
||||
{
|
||||
println!("# waiting {}ms", start_time.elapsed().as_millis());
|
||||
}
|
||||
|
||||
let c = match &mut child {
|
||||
Some(child) => child,
|
||||
None => match rx.try_recv() {
|
||||
Ok(Ok(c)) => {
|
||||
child = Some(c);
|
||||
continue;
|
||||
}
|
||||
Ok(Err(err)) => {
|
||||
let failure = format!("{}: failed to execute: {}", bin, err);
|
||||
println!("{}", failure);
|
||||
failures.push(failure);
|
||||
break;
|
||||
}
|
||||
Err(mpsc::TryRecvError::Disconnected) => {
|
||||
let failure = format!("{}: failed to execute: thread died", bin);
|
||||
println!("{}", failure);
|
||||
failures.push(failure);
|
||||
break;
|
||||
}
|
||||
Err(mpsc::TryRecvError::Empty) => {
|
||||
thread::sleep(Duration::from_millis(if start_time.elapsed() < slowtime {
|
||||
25
|
||||
} else {
|
||||
500
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
match c.try_wait() {
|
||||
Ok(Some(s)) => {
|
||||
status = Some(s);
|
||||
break;
|
||||
}
|
||||
Ok(None) => {
|
||||
thread::sleep(Duration::from_millis(if start_time.elapsed() < slowtime {
|
||||
25
|
||||
} else {
|
||||
500
|
||||
}));
|
||||
}
|
||||
Err(e) => {
|
||||
failures.push(format!("{}: error waiting: {}", bin, e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match (status, child) {
|
||||
(Some(exit_status), Some(child)) => {
|
||||
if !status_only {
|
||||
if let Err(failure) = expected(&bin, "stdout", &output.stdout, output.status) {
|
||||
let mut stdout = Vec::new();
|
||||
let mut stderr = Vec::new();
|
||||
child.stdout.unwrap().read_to_end(&mut stdout).unwrap();
|
||||
child.stderr.unwrap().read_to_end(&mut stderr).unwrap();
|
||||
|
||||
if let Err(failure) = expected(&bin, "stdout", &stdout, exit_status) {
|
||||
println!("{}", failure);
|
||||
failures.push(failure);
|
||||
}
|
||||
|
||||
if let Err(failure) = expected(&bin, "stderr", &output.stderr, output.status) {
|
||||
if let Err(failure) = expected(&bin, "stderr", &stderr, exit_status) {
|
||||
println!("{}", failure);
|
||||
failures.push(failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
let failure = format!("{}: failed to execute: {}", bin, err);
|
||||
println!("{}", failure);
|
||||
failures.push(failure);
|
||||
(_, _) => {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if start_time.elapsed() > slowtime {
|
||||
println!(
|
||||
"\x1b[0;93;49m test exection took too long: {}ms\x1b[0m",
|
||||
start_time.elapsed().as_millis()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if !failures.is_empty() {
|
||||
println!("# FAILURES #");
|
||||
println!("\x1b[1;91;49m# FAILURES #\x1b[0m");
|
||||
for failure in failures {
|
||||
println!("{}", failure);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ static bool check_mode(
|
||||
stderr,
|
||||
"Mode mismatch\n\tExpected: %o\n\tActual: %o\n",
|
||||
expected,
|
||||
stat.st_mode
|
||||
stat.st_mode & 0777
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ void handler(int _s)
|
||||
int main(void)
|
||||
{
|
||||
// sleep has no error codes and doesn't set errno
|
||||
unsigned int unslept = sleep(2);
|
||||
unsigned int unslept = sleep(1);
|
||||
printf("unslept: %u\n", unslept);
|
||||
|
||||
struct sigaction sa;
|
||||
@@ -23,7 +23,7 @@ int main(void)
|
||||
sa.sa_handler = handler;
|
||||
sigaction(SIGALRM, &sa, NULL);
|
||||
// TODO: This test is unreliable, overlapping use of alarm and sleep is not recommended.
|
||||
// alarm(2);
|
||||
// alarm(1);
|
||||
|
||||
// unslept = sleep(10);
|
||||
// if (unslept < 7)
|
||||
@@ -32,7 +32,7 @@ int main(void)
|
||||
// exit(EXIT_FAILURE);
|
||||
// }
|
||||
|
||||
int us_status = usleep(1000);
|
||||
int us_status = usleep(100);
|
||||
ERROR_IF(usleep, us_status, == -1);
|
||||
UNEXP_IF(usleep, us_status, != 0);
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ void for_code(int code) {
|
||||
// Testing successful exit
|
||||
if (pid == 0) {
|
||||
// child
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
_Exit(code);
|
||||
}
|
||||
printf("Testing waitpid of child %d for code %d\n", pid, code);
|
||||
|
||||
@@ -15,7 +15,7 @@ int main(void) {
|
||||
|
||||
if (pid_samepgid == 0) {
|
||||
// child
|
||||
sleep(2);
|
||||
usleep(200);
|
||||
_Exit(2);
|
||||
}
|
||||
pid_t pid_diffpgids[2];
|
||||
@@ -28,7 +28,7 @@ int main(void) {
|
||||
ERROR_IF(setpgid, ret, == -1);
|
||||
|
||||
// child
|
||||
sleep(1);
|
||||
usleep(100);
|
||||
_Exit(i);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user