void LightProcess::Initialize(const std::string &prefix, int count, const std::vector<int> &inherited_fds) { if (prefix.empty() || count <= 0) { return; } if (Available()) { // already initialized return; } g_procs.reset(new LightProcess[count]); g_procsCount = count; auto afdt_filename = folly::sformat("{}.{}", prefix, getpid()); // remove the possible leftover remove(afdt_filename.c_str()); afdt_error_t err = AFDT_ERROR_T_INIT; auto afdt_lid = afdt_listen(afdt_filename.c_str(), &err); if (afdt_lid < 0) { Logger::Warning("Unable to afdt_listen to %s: %d %s", afdt_filename.c_str(), errno, folly::errnoStr(errno).c_str()); return; } SCOPE_EXIT { ::close(afdt_lid); remove(afdt_filename.c_str()); }; for (int i = 0; i < count; i++) { if (!g_procs[i].initShadow(afdt_lid, afdt_filename, i, inherited_fds)) { for (int j = 0; j < i; j++) { g_procs[j].closeShadow(); } g_procs.reset(); g_procsCount = 0; break; } } if (!s_handlerInited) { struct sigaction sa; struct sigaction old_sa; sa.sa_sigaction = &LightProcess::SigChldHandler; sa.sa_flags = SA_SIGINFO | SA_NOCLDSTOP; if (sigaction(SIGCHLD, &sa, &old_sa) != 0) { Logger::Error("Couldn't install SIGCHLD handler"); abort(); } s_handlerInited = true; } }
int afdt_create_server( const char* fname, struct event_base* eb, afdt_request_handler_t request_handler, afdt_post_handler_t post_handler, afdt_error_handler_t error_handler, void** out_close_handle, void* userdata ) { int ret; struct afdt_error_t err = AFDT_ERROR_T_INIT; err.phase = AFDT_CREATE_SERVER; struct ev_arg* ev_userdata = malloc(sizeof(*ev_userdata)); if (ev_userdata == NULL) { set_error(&err, AFDT_MALLOC, ""); error_handler(&err, userdata); return -1; } ev_userdata->eb = eb; ev_userdata->request_handler = request_handler; ev_userdata->response_handler = NULL; ev_userdata->post_handler = post_handler; ev_userdata->error_handler = error_handler; ev_userdata->afdt_userdata = userdata; ret = afdt_listen(fname, &err); if (ret < 0) { goto destruct; } int acceptfd = ret; enum afdt_operation err_op = AFDT_NO_OPERATION; event_set(&ev_userdata->ev, acceptfd, EV_READ | EV_PERSIST, server_handle_accept_read, ev_userdata); ret = event_bsa(eb, &ev_userdata->ev, NULL, &err_op); if (ret < 0) { set_error(&err, err_op, ""); goto destruct; } if (out_close_handle != NULL) { *out_close_handle = ev_userdata; } return 0; destruct: error_handler(&err, userdata); free(ev_userdata); return ret; }
bool LightProcess::initShadow(const std::string &prefix, int id, const std::vector<int> &inherited_fds) { Lock lock(m_procMutex); std::ostringstream os; os << prefix << "." << getpid() << "." << id; m_afdtFilename = os.str(); // remove the possible leftover remove(m_afdtFilename.c_str()); afdt_error_t err; m_afdt_lfd = afdt_listen(m_afdtFilename.c_str(), &err); if (m_afdt_lfd < 0) { Logger::Warning("Unable to afdt_listen to %s: %d %s", m_afdtFilename.c_str(), errno, folly::errnoStr(errno).c_str()); return false; } CPipe p1, p2; if (!p1.open() || !p2.open()) { Logger::Warning("Unable to create pipe: %d %s", errno, folly::errnoStr(errno).c_str()); return false; } pid_t child = fork(); if (child == 0) { // child pid_t sid = setsid(); if (sid < 0) { Logger::Warning("Unable to setsid"); exit(-1); } m_afdt_fd = afdt_connect(m_afdtFilename.c_str(), &err); if (m_afdt_fd < 0) { Logger::Warning("Unable to afdt_connect, filename %s: %d %s", m_afdtFilename.c_str(), errno, folly::errnoStr(errno).c_str()); exit(-1); } int fd1 = p1.detachOut(); int fd2 = p2.detachIn(); p1.close(); p2.close(); // don't hold on to previous light processes' pipes, inherited // fds, or the afdt listening socket for (int i = 0; i < id; i++) { g_procs[i].closeFiles(); } close_fds(inherited_fds); ::close(m_afdt_lfd); runShadow(fd1, fd2); } else if (child < 0) { // failed Logger::Warning("Unable to fork lightly: %d %s", errno, folly::errnoStr(errno).c_str()); return false; } else { // parent m_fin = fdopen(p2.detachOut(), "r"); m_fout = fdopen(p1.detachIn(), "w"); m_shadowProcess = child; sockaddr addr; socklen_t addrlen = sizeof(addr); m_afdt_fd = accept(m_afdt_lfd, &addr, &addrlen); if (m_afdt_fd < 0) { Logger::Warning("Unable to establish afdt connection: %d %s", errno, folly::errnoStr(errno).c_str()); closeShadow(); return false; } } return true; }