update path setup in scripts/test-all-syscalls-sequentially.sh
[trinity.git] / child.c
blob94435b1f23287b954c8c88fab400ebd0dfdc7927
1 /*
2 * Each process that gets forked runs this code.
3 */
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <sched.h>
12 #include <sys/time.h>
13 #include <sys/resource.h>
14 #include <sys/prctl.h>
16 #include "arch.h"
17 #include "child.h"
18 #include "list.h"
19 #include "log.h"
20 #include "maps.h"
21 #include "params.h" // for 'debug'
22 #include "pids.h"
23 #include "random.h"
24 #include "shm.h"
25 #include "signals.h"
26 #include "syscall.h"
27 #include "tables.h"
28 #include "trinity.h" // ARRAY_SIZE
29 #include "utils.h" // zmalloc
31 static void disable_coredumps(void)
33 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
35 if (debug == TRUE) {
36 (void)signal(SIGABRT, SIG_DFL);
37 (void)signal(SIGSEGV, SIG_DFL);
38 return;
41 if (setrlimit(RLIMIT_CORE, &limit) != 0)
42 perror( "setrlimit(RLIMIT_CORE)" );
44 prctl(PR_SET_DUMPABLE, FALSE);
47 static void enable_coredumps(void)
49 struct rlimit limit = {
50 .rlim_cur = RLIM_INFINITY,
51 .rlim_max = RLIM_INFINITY
54 if (debug == TRUE)
55 return;
57 prctl(PR_SET_DUMPABLE, TRUE);
59 (void) setrlimit(RLIMIT_CORE, &limit);
61 static void set_make_it_fail(void)
63 int fd;
64 const char *buf = "1";
66 /* If we failed last time, don't bother trying in future. */
67 if (shm->do_make_it_fail == TRUE)
68 return;
70 fd = open("/proc/self/make-it-fail", O_WRONLY);
71 if (fd == -1)
72 return;
74 if (write(fd, buf, 1) == -1) {
75 if (errno != EPERM)
76 outputerr("writing to /proc/self/make-it-fail failed! (%s)\n", strerror(errno));
77 else
78 shm->do_make_it_fail = TRUE;
80 close(fd);
84 * We call this occasionally to set some FPU state, in the hopes that we
85 * might tickle some weird FPU/scheduler related bugs
87 static void use_fpu(void)
89 double x = 0;
90 asm volatile("":"+m" (x));
91 x += 1;
92 asm volatile("":"+m" (x));
95 int this_child = 0;
97 static void setup_page_maps(void)
99 unsigned long *page;
100 unsigned int i;
102 page = (void *) page_maps;
104 for (i = 0; i < page_size / sizeof(unsigned long); i++) {
105 struct map *map;
107 map = get_map();
108 page[i] = (unsigned long) map->ptr;
112 void init_child(int childno)
114 cpu_set_t set;
115 pid_t pid = getpid();
117 this_child = childno;
119 set_seed(childno);
121 shm->kill_count[childno] = 0;
123 shm->num_mappings[childno] = 0;
124 shm->mappings[childno] = zmalloc(sizeof(struct map));
125 INIT_LIST_HEAD(&shm->mappings[childno]->list);
127 setup_page_maps();
129 if (sched_getaffinity(pid, sizeof(set), &set) == 0) {
130 CPU_ZERO(&set);
131 CPU_SET(childno, &set);
132 sched_setaffinity(pid, sizeof(set), &set);
135 shm->child_syscall_count[childno] = 0;
137 set_make_it_fail();
139 if (rand() % 100 < 50)
140 use_fpu();
142 disable_coredumps();
145 void check_parent_pid(void)
147 pid_t pid;
148 unsigned int i;
149 static unsigned int parent_check_time = 10;
151 parent_check_time--;
152 if (parent_check_time != 0)
153 return;
155 parent_check_time = 10;
157 if (getppid() == shm->mainpid)
158 return;
160 pid = getpid();
162 //FIXME: Add locking so only one child does this output.
163 output(0, BUGTXT "CHILD (pid:%d) GOT REPARENTED! "
164 "parent pid:%d. Watchdog pid:%d\n",
165 pid, shm->mainpid, watchdog_pid);
166 output(0, BUGTXT "Last syscalls:\n");
168 for_each_pidslot(i) {
169 // Skip over 'boring' entries.
170 if ((shm->pids[i] == EMPTY_PIDSLOT) &&
171 (shm->previous_syscallno[i] == 0) &&
172 (shm->child_syscall_count[i] == 0))
173 continue;
175 output(0, "[%d] pid:%d call:%s callno:%d\n",
176 i, shm->pids[i],
177 print_syscall_name(shm->previous_syscallno[i], shm->do32bit[i]), // FIXME: need previous do32bit
178 shm->child_syscall_count[i]);
180 shm->exit_reason = EXIT_REPARENT_PROBLEM;
181 exit(EXIT_FAILURE);
182 //TODO: Emergency logging.
185 struct child_funcs {
186 int type;
187 const char *name;
188 int (*func)(int childno);
191 static const struct child_funcs child_functions[] = {
192 { .type = CHILD_RANDOM_SYSCALLS, .name = "rand_syscalls", .func = child_random_syscalls },
193 #ifdef DEBUG_MULTI
194 { .type = CHILD_OPEN_ALL_FILES, .name = "read_all_files", .func = child_read_all_files },
195 #endif
198 int child_process(int childno)
200 int ret;
201 unsigned int i;
203 i = rand() % ARRAY_SIZE(child_functions);
205 #ifdef DEBUG_MULTI
206 output(0, "Chose %s.\n", child_functions[i].name);
207 #endif
209 shm->child_type[childno] = child_functions[i].type;
210 ret = child_functions[i].func(childno);
212 enable_coredumps();
214 return ret;