missing address-of op.
[trinity.git] / child.c
blob9dd5494489a370e89b1ee675f887aed7082c41a7
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 "child.h"
17 #include "syscall.h"
18 #include "log.h"
19 #include "random.h"
20 #include "shm.h"
21 #include "signals.h"
22 #include "pids.h"
23 #include "params.h" // for 'debug'
24 #include "tables.h"
25 #include "trinity.h" // ARRAY_SIZE
27 static struct rlimit oldrlimit;
29 static void disable_coredumps(void)
31 struct rlimit limit;
33 if (debug == TRUE) {
34 (void)signal(SIGSEGV, SIG_DFL);
35 return;
38 getrlimit(RLIMIT_CORE, &oldrlimit);
40 limit.rlim_cur = 0;
41 limit.rlim_max = oldrlimit.rlim_max;
42 if (setrlimit(RLIMIT_CORE, &limit) != 0)
43 perror( "setrlimit(RLIMIT_CORE)" );
46 static void reenable_coredumps(void)
48 if (debug == TRUE)
49 return;
51 prctl(PR_SET_DUMPABLE, TRUE);
53 if (setrlimit(RLIMIT_CORE, &oldrlimit) != 0) {
54 outputerr("[%d] Error restoring rlimits to cur:%d max:%d (%s)\n",
55 getpid(),
56 (unsigned int) oldrlimit.rlim_cur,
57 (unsigned int) oldrlimit.rlim_max,
58 strerror(errno));
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 void init_child(int childno)
97 cpu_set_t set;
98 pid_t pid = getpid();
100 set_seed(childno);
102 shm->kill_count[childno] = 0;
104 disable_coredumps();
106 if (sched_getaffinity(pid, sizeof(set), &set) == 0) {
107 CPU_ZERO(&set);
108 CPU_SET(childno, &set);
109 sched_setaffinity(pid, sizeof(set), &set);
112 shm->child_syscall_count[childno] = 0;
114 set_make_it_fail();
116 if (rand() % 100 < 50)
117 use_fpu();
120 void check_parent_pid(void)
122 pid_t pid;
123 unsigned int i;
124 static unsigned int parent_check_time = 10;
126 parent_check_time--;
127 if (parent_check_time != 0)
128 return;
130 parent_check_time = 10;
132 if (getppid() == shm->mainpid)
133 return;
135 pid = getpid();
137 //FIXME: Add locking so only one child does this output.
138 output(0, BUGTXT "CHILD (pid:%d) GOT REPARENTED! "
139 "parent pid:%d. Watchdog pid:%d\n",
140 pid, shm->mainpid, watchdog_pid);
141 output(0, BUGTXT "Last syscalls:\n");
143 for (i = 0; i < MAX_NR_CHILDREN; i++) {
144 // Skip over 'boring' entries.
145 if ((shm->pids[i] == -1) &&
146 (shm->previous_syscallno[i] == 0) &&
147 (shm->child_syscall_count[i] == 0))
148 continue;
150 output(0, "[%d] pid:%d call:%s callno:%d\n",
151 i, shm->pids[i],
152 print_syscall_name(shm->previous_syscallno[i], shm->do32bit[i]), // FIXME: need previous do32bit
153 shm->child_syscall_count[i]);
155 shm->exit_reason = EXIT_REPARENT_PROBLEM;
156 exit(EXIT_FAILURE);
157 //TODO: Emergency logging.
160 struct child_funcs {
161 int type;
162 const char *name;
163 int (*func)(int childno);
166 static const struct child_funcs child_functions[] = {
167 { .type = CHILD_RANDOM_SYSCALLS, .name = "rand_syscalls", .func = child_random_syscalls },
168 #ifdef DEBUG_MULTI
169 { .type = CHILD_OPEN_ALL_FILES, .name = "read_all_files", .func = child_read_all_files },
170 #endif
173 int child_process(int childno)
175 int ret;
176 unsigned int i;
178 i = rand() % ARRAY_SIZE(child_functions);
180 #ifdef DEBUG_MULTI
181 output(0, "Chose %s.\n", child_functions[i].name);
182 #endif
184 shm->child_type[childno] = child_functions[i].type;
185 ret = child_functions[i].func(childno);
187 reenable_coredumps();
189 return ret;