make a bunch of sparse missing prototype warnings go away
[trinity.git] / child.c
blob27d3d8357eb49cc39074c35427f2af2d130866af
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 struct rlimit oldrlimit;
33 static void disable_coredumps(void)
35 struct rlimit limit;
37 if (debug == TRUE) {
38 (void)signal(SIGABRT, SIG_DFL);
39 (void)signal(SIGSEGV, SIG_DFL);
40 return;
43 getrlimit(RLIMIT_CORE, &oldrlimit);
45 limit.rlim_cur = 0;
46 limit.rlim_max = oldrlimit.rlim_max;
47 if (setrlimit(RLIMIT_CORE, &limit) != 0)
48 perror( "setrlimit(RLIMIT_CORE)" );
51 static void reenable_coredumps(void)
53 if (debug == TRUE)
54 return;
56 prctl(PR_SET_DUMPABLE, TRUE);
58 if (setrlimit(RLIMIT_CORE, &oldrlimit) != 0) {
59 outputerr("[%d] Error restoring rlimits to cur:%d max:%d (%s)\n",
60 getpid(),
61 (unsigned int) oldrlimit.rlim_cur,
62 (unsigned int) oldrlimit.rlim_max,
63 strerror(errno));
66 static void set_make_it_fail(void)
68 int fd;
69 const char *buf = "1";
71 /* If we failed last time, don't bother trying in future. */
72 if (shm->do_make_it_fail == TRUE)
73 return;
75 fd = open("/proc/self/make-it-fail", O_WRONLY);
76 if (fd == -1)
77 return;
79 if (write(fd, buf, 1) == -1) {
80 if (errno != EPERM)
81 outputerr("writing to /proc/self/make-it-fail failed! (%s)\n", strerror(errno));
82 else
83 shm->do_make_it_fail = TRUE;
85 close(fd);
89 * We call this occasionally to set some FPU state, in the hopes that we
90 * might tickle some weird FPU/scheduler related bugs
92 static void use_fpu(void)
94 double x = 0;
95 asm volatile("":"+m" (x));
96 x += 1;
97 asm volatile("":"+m" (x));
100 int this_child = 0;
102 static void setup_page_maps(void)
104 unsigned long *page;
105 unsigned int i;
107 page = (void *) page_maps;
109 for (i = 0; i < page_size / sizeof(unsigned long); i++) {
110 struct map *map;
112 map = get_map();
113 page[i] = (unsigned long) map->ptr;
117 void init_child(int childno)
119 cpu_set_t set;
120 pid_t pid = getpid();
122 this_child = childno;
124 set_seed(childno);
126 shm->kill_count[childno] = 0;
128 disable_coredumps();
130 setup_page_maps();
132 if (sched_getaffinity(pid, sizeof(set), &set) == 0) {
133 CPU_ZERO(&set);
134 CPU_SET(childno, &set);
135 sched_setaffinity(pid, sizeof(set), &set);
138 shm->child_syscall_count[childno] = 0;
140 set_make_it_fail();
142 if (rand() % 100 < 50)
143 use_fpu();
145 shm->num_mappings[childno] = 0;
146 shm->mappings[childno] = zmalloc(sizeof(struct map));
147 INIT_LIST_HEAD(&shm->mappings[childno]->list);
150 void check_parent_pid(void)
152 pid_t pid;
153 unsigned int i;
154 static unsigned int parent_check_time = 10;
156 parent_check_time--;
157 if (parent_check_time != 0)
158 return;
160 parent_check_time = 10;
162 if (getppid() == shm->mainpid)
163 return;
165 pid = getpid();
167 //FIXME: Add locking so only one child does this output.
168 output(0, BUGTXT "CHILD (pid:%d) GOT REPARENTED! "
169 "parent pid:%d. Watchdog pid:%d\n",
170 pid, shm->mainpid, watchdog_pid);
171 output(0, BUGTXT "Last syscalls:\n");
173 for_each_pidslot(i) {
174 // Skip over 'boring' entries.
175 if ((shm->pids[i] == EMPTY_PIDSLOT) &&
176 (shm->previous_syscallno[i] == 0) &&
177 (shm->child_syscall_count[i] == 0))
178 continue;
180 output(0, "[%d] pid:%d call:%s callno:%d\n",
181 i, shm->pids[i],
182 print_syscall_name(shm->previous_syscallno[i], shm->do32bit[i]), // FIXME: need previous do32bit
183 shm->child_syscall_count[i]);
185 shm->exit_reason = EXIT_REPARENT_PROBLEM;
186 exit(EXIT_FAILURE);
187 //TODO: Emergency logging.
190 struct child_funcs {
191 int type;
192 const char *name;
193 int (*func)(int childno);
196 static const struct child_funcs child_functions[] = {
197 { .type = CHILD_RANDOM_SYSCALLS, .name = "rand_syscalls", .func = child_random_syscalls },
198 #ifdef DEBUG_MULTI
199 { .type = CHILD_OPEN_ALL_FILES, .name = "read_all_files", .func = child_read_all_files },
200 #endif
203 int child_process(int childno)
205 int ret;
206 unsigned int i;
208 i = rand() % ARRAY_SIZE(child_functions);
210 #ifdef DEBUG_MULTI
211 output(0, "Chose %s.\n", child_functions[i].name);
212 #endif
214 shm->child_type[childno] = child_functions[i].type;
215 ret = child_functions[i].func(childno);
217 reenable_coredumps();
219 return ret;