int afdt_create_client( const char* fname, struct event_base* eb, const uint8_t* request, uint32_t request_length, afdt_response_handler_t response_handler, afdt_error_handler_t error_handler, const struct timeval* timeout, void* userdata) { int ret; struct afdt_error_t err = AFDT_ERROR_T_INIT; err.phase = AFDT_CREATE_CLIENT; 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 = NULL; ev_userdata->response_handler = response_handler; ev_userdata->post_handler = NULL; ev_userdata->error_handler = error_handler; ev_userdata->afdt_userdata = userdata; ret = afdt_connect(fname, &err); if (ret < 0) { goto socket_failed; } int connfd = ret; ret = afdt_send_plain_msg(connfd, request, request_length, &err); if (ret < 0) { goto write_failed; } enum afdt_operation err_op = AFDT_NO_OPERATION; event_set(&ev_userdata->ev, connfd, EV_READ, client_handle_read, ev_userdata); ret = event_bsa(eb, &ev_userdata->ev, timeout, &err_op); if (ret < 0) { set_error(&err, err_op, ""); goto event_failed; } return 0; int errno_save; write_failed: event_failed: errno_save = errno; close(connfd); errno = errno_save; socket_failed: error_handler(&err, userdata); free(ev_userdata); return ret; }
bool LightProcess::initShadow(int afdt_lid, const std::string &afdt_filename, int id, const std::vector<int> &inherited_fds) { Lock lock(m_procMutex); pid_t child = fork(); if (child == 0) { // child Logger::ResetPid(); pid_t sid = setsid(); if (sid < 0) { Logger::Warning("Unable to setsid"); exit(HPHP_EXIT_FAILURE); } afdt_error_t err = AFDT_ERROR_T_INIT; m_afdt_fd = afdt_connect(afdt_filename.c_str(), &err); if (m_afdt_fd < 0) { Logger::Warning("Unable to afdt_connect, filename %s: %d %s", afdt_filename.c_str(), errno, folly::errnoStr(errno).c_str()); exit(HPHP_EXIT_FAILURE); } // 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(afdt_lid); runShadow(); } else if (child < 0) { // failed Logger::Warning("Unable to fork lightly: %d %s", errno, folly::errnoStr(errno).c_str()); return false; } else { // parent m_shadowProcess = child; sockaddr addr; socklen_t addrlen = sizeof(addr); m_afdt_fd = accept(afdt_lid, &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; }
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; }