int fork() { int pid; init(); if (forked) { return real_fork(); } pid = real_fork(); if (pid == 0) { forked = 1; } else if (pid > 0) { // no SSL_shutdown(ssl_ssl) as it also terminates connection in fork! SSL_free(ssl_ssl); real_close(ssl_socket); } return pid; }
static void _sigio_child(ng_tapnet_t *dev) { pid_t parent = _native_pid; if ((_sigio_child_pid = real_fork()) == -1) { err(EXIT_FAILURE, "sigio_child: fork"); } if (_sigio_child_pid > 0) { /* return in parent process */ return; } /* watch tap interface and signal parent process if data is * available */ fd_set rfds; while (1) { FD_ZERO(&rfds); FD_SET(dev->tap_fd, &rfds); if (real_select(dev->tap_fd + 1, &rfds, NULL, NULL, NULL) == 1) { kill(parent, SIGIO); } else { kill(parent, SIGKILL); err(EXIT_FAILURE, "osx_sigio_child: select"); } pause(); } }
/***************************************************** when we fork we have to close all connections and files in the child *******************************************************/ int smbw_fork(void) { pid_t child; int p[2]; char c=0; pstring line; struct smbw_file *file, *next_file; struct smbw_server *srv, *next_srv; if (pipe(p)) return real_fork(); child = real_fork(); if (child) { /* block the parent for a moment until the sockets are closed */ close(p[1]); read(p[0], &c, 1); close(p[0]); return child; } close(p[0]); /* close all files */ for (file=smbw_files;file;file=next_file) { next_file = file->next; close(file->fd); } /* close all server connections */ for (srv=smbw_srvs;srv;srv=next_srv) { next_srv = srv->next; smbw_srv_close(srv); } slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid()); smbw_setshared(line,smbw_cwd); /* unblock the parent */ write(p[1], &c, 1); close(p[1]); /* and continue in the child */ return 0; }
pid_t fork(void) throw() { pid_t retval; print_trace ("%*sfork()=...\n", indent, "" ); indent+=2; /* call the real fork function */ retval = real_fork (); indent-=2; print_trace ("%*sfork()=%d\n", indent, "" , retval); return retval; }
pid_t fork(void) { static int (*real_fork)(void) = NULL; pid_t ret; if (!real_fork) { real_fork = dlsym(RTLD_NEXT, "fork"); } ret = real_fork(); if (-1 == ret) { FSOCKET_ERR("FSOCKET: fork failed!\n"); } else if (0 == ret) { // Child process if (fsocket_channel_fd >= 0) { struct fsocket_ioctl_arg arg; memset(&arg, 0, sizeof(arg)); // Spawn all listenning socket ioctl(fsocket_channel_fd, FSOCKET_IOC_SPAWN_ALL_LISTEN, &arg); } } return ret; }
/* * Add a fork node to the subgraph add then add an additional parent of * either all zeroes or all ones depending on whether we're in child or parent, * respectively. */ pid_t action_fork(void) { // Lock both parent (self) and master struct process *process = lock_process(); struct process *master = process->master ? find_process_info(process->master) : process; if (process != master) spin_lock(&master->lock); // Save mutable information about process struct fd_map fds = process->fds; int flags = process->flags; // Analyze open file descriptors int linked = 0, fd; for (fd = 0; fd < MAX_FDS; fd++) { int slot = fds.map[fd]; if (slot) { struct fd_info *info = fds.info + slot; if (info->flags & WO_PIPE) { wlog("fork: fd %d as pipe", fd); linked = 1; } else if (info->flags & O_WRONLY) // TODO: Enforce that files aren't written by more than // one process. This requires tracking writes, etc. wlog("fork: fd %d open for write", fd); else // TODO: Link processes that share open read descriptors, or // possibly create duplicate read nodes for more precision. wlog("fork: fd %d open for read", fd); } } struct hash zero_hash, one_hash; memset(&zero_hash, 0, sizeof(struct hash)); memset(&one_hash, -1, sizeof(struct hash)); // Add a fork node to the subgraph new_node(master, SG_FORK, linked ? &zero_hash : &zero_hash); struct hash fork_node = master->parents.p[0]; wlog("fork: linked %d", linked); // Actually fork pid_t pid = real_fork(); if (pid < 0) die("action_fork: fork failed: %s", strerror(errno)); if (!pid) { struct process *child = new_process_info(); child->flags = flags; if (linked) { wlog("linking to %d", master->pid); child->master = master->pid; } else { wlog("child of %d (master %d)", process->pid, master->pid); // Inherit from fork node and zero add_parent(child, &fork_node); add_parent(child, &zero_hash); wlog("fresh process: master 0x%x", child->master); } // Copy fd_map information to child memcpy(&child->fds, &fds, sizeof(struct fd_map)); // Drop fds with close-on-exec set int fd; for (fd = 0; fd < MAX_FDS; fd++) if (child->fds.cloexec[fd]) child->fds.map[fd] = 0; unlock_process(); } else { if (!linked) { // Add a one parent node to the parent add_parent(master, &one_hash); } // Unlock both parent (self) and master if (process->master) spin_unlock(&master->lock); unlock_process(); } fd_map_dump(); return pid; }