66
66
#include <sys/wait.h>
67
67
#include <unistd.h>
68
68
#include <setjmp.h>
69
- #include <syscall.h>
70
- #include <linux/sched.h>
71
69
72
70
#include "kselftest.h"
73
71
82
80
# define TH_LOG_ENABLED 1
83
81
#endif
84
82
85
- /* Wait for the child process to end but without sharing memory mapping. */
86
- static inline pid_t clone3_vfork (void )
87
- {
88
- struct clone_args args = {
89
- .flags = CLONE_VFORK ,
90
- .exit_signal = SIGCHLD ,
91
- };
92
-
93
- return syscall (__NR_clone3 , & args , sizeof (args ));
94
- }
95
-
96
83
/**
97
84
* TH_LOG()
98
85
*
@@ -437,7 +424,7 @@ static inline pid_t clone3_vfork(void)
437
424
} \
438
425
if (setjmp (_metadata -> env ) == 0 ) { \
439
426
/* _metadata and potentially self are shared with all forks. */ \
440
- child = clone3_vfork (); \
427
+ child = fork (); \
441
428
if (child == 0 ) { \
442
429
fixture_name ##_setup (_metadata , self , variant -> data ); \
443
430
/* Let setup failure terminate early. */ \
@@ -1016,7 +1003,14 @@ void __wait_for_test(struct __test_metadata *t)
1016
1003
.sa_flags = SA_SIGINFO ,
1017
1004
};
1018
1005
struct sigaction saved_action ;
1019
- int status ;
1006
+ /*
1007
+ * Sets status so that WIFEXITED(status) returns true and
1008
+ * WEXITSTATUS(status) returns KSFT_FAIL. This safe default value
1009
+ * should never be evaluated because of the waitpid(2) check and
1010
+ * SIGALRM handling.
1011
+ */
1012
+ int status = KSFT_FAIL << 8 ;
1013
+ int child ;
1020
1014
1021
1015
if (sigaction (SIGALRM , & action , & saved_action )) {
1022
1016
t -> exit_code = KSFT_FAIL ;
@@ -1028,7 +1022,15 @@ void __wait_for_test(struct __test_metadata *t)
1028
1022
__active_test = t ;
1029
1023
t -> timed_out = false;
1030
1024
alarm (t -> timeout );
1031
- waitpid (t -> pid , & status , 0 );
1025
+ child = waitpid (t -> pid , & status , 0 );
1026
+ if (child == -1 && errno != EINTR ) {
1027
+ t -> exit_code = KSFT_FAIL ;
1028
+ fprintf (TH_LOG_STREAM ,
1029
+ "# %s: Failed to wait for PID %d (errno: %d)\n" ,
1030
+ t -> name , t -> pid , errno );
1031
+ return ;
1032
+ }
1033
+
1032
1034
alarm (0 );
1033
1035
if (sigaction (SIGALRM , & saved_action , NULL )) {
1034
1036
t -> exit_code = KSFT_FAIL ;
@@ -1083,6 +1085,7 @@ void __wait_for_test(struct __test_metadata *t)
1083
1085
WTERMSIG (status ));
1084
1086
}
1085
1087
} else {
1088
+ t -> exit_code = KSFT_FAIL ;
1086
1089
fprintf (TH_LOG_STREAM ,
1087
1090
"# %s: Test ended in some other way [%u]\n" ,
1088
1091
t -> name ,
@@ -1218,6 +1221,7 @@ void __run_test(struct __fixture_metadata *f,
1218
1221
struct __test_xfail * xfail ;
1219
1222
char test_name [1024 ];
1220
1223
const char * diagnostic ;
1224
+ int child ;
1221
1225
1222
1226
/* reset test struct */
1223
1227
t -> exit_code = KSFT_PASS ;
@@ -1236,15 +1240,16 @@ void __run_test(struct __fixture_metadata *f,
1236
1240
fflush (stdout );
1237
1241
fflush (stderr );
1238
1242
1239
- t -> pid = clone3_vfork ();
1240
- if (t -> pid < 0 ) {
1243
+ child = fork ();
1244
+ if (child < 0 ) {
1241
1245
ksft_print_msg ("ERROR SPAWNING TEST CHILD\n" );
1242
1246
t -> exit_code = KSFT_FAIL ;
1243
- } else if (t -> pid == 0 ) {
1247
+ } else if (child == 0 ) {
1244
1248
setpgrp ();
1245
1249
t -> fn (t , variant );
1246
1250
_exit (t -> exit_code );
1247
1251
} else {
1252
+ t -> pid = child ;
1248
1253
__wait_for_test (t );
1249
1254
}
1250
1255
ksft_print_msg (" %4s %s\n" ,
0 commit comments