void LibEventServerWithTakeover::start() { if (m_server_ssl) { // Set a flag to prevent parent class from trying to listen to ssl // before the old server releases the port m_accept_sock_ssl = -2; } LibEventServer::start(); if (m_took_over) { Logger::Info("takeover: requesting shutdown of satellites"); // Use AFDT to synchronously shut down the old server's satellites // so we can take their ports using accept. The main server will be // stopped asynchronously. uint8_t shutdown_request[3] = P_VERSION C_TERM_REQ; uint8_t shutdown_response[3] = {0,0,0}; uint32_t response_len = sizeof(shutdown_response); int should_not_receive_fd; afdt_error_t err = AFDT_ERROR_T_INIT; // TODO(dreiss): Make this timeout configurable. // We can aford to wait a long time here, since we've already started // the dispatcher for this server. We want to give the old server // plenty of time to shut down all of its satellite servers. struct timeval timeout = { 10 , 0 }; int ret = afdt_sync_client( m_transfer_fname.c_str(), shutdown_request, sizeof(shutdown_request) - 1, shutdown_response, &response_len, &should_not_receive_fd, &timeout, &err); if (ret < 0) { fd_transfer_error_hander(&err, nullptr); Logger::Warning("Failed to shut-down old server with AFDT."); // The higher-level start logic will try *very* hard to recover from this. } String resp((const char*)shutdown_response, response_len, CopyString); if (resp != s_ver_C_TERM_OK) { Logger::Error( "Old server could not shut down: " "response = '%s'", f_addcslashes(resp, null_string).data()); } else { Logger::Info("takeover: old satellites have shut down"); } } if (m_server_ssl) { if (getAcceptSocketSSL() != 0) { Logger::Error("Fail to listen on ssl port %d", m_port_ssl); throw FailedToListenException(m_address, m_port_ssl); } Logger::Info("Listen on ssl port %d",m_port_ssl); } setupFdServer(); }
bool TestExtString::test_addcslashes() { VS(f_addcslashes("ABCDEFGH\n", "A..D\n"), "\\A\\B\\C\\DEFGH\\n"); VS(f_addcslashes(String("\x00\x0D\n", 3, AttachLiteral), null_string), "\\000\\r\\n"); return Count(true); }
int LibEventServerWithTakeover::getAcceptSocket() { int ret; const char *address = m_address.empty() ? nullptr : m_address.c_str(); if (m_accept_sock != -1) { Logger::Warning("LibEventServerWithTakeover trying to get a socket, " "but m_accept_sock is not -1. Possibly leaking file descriptors."); m_accept_sock = -1; } ret = evhttp_bind_socket_backlog_fd(m_server, address, m_port, RuntimeOption::ServerBacklog); if (ret >= 0) { Logger::Info("takeover: bound directly to port %d", m_port); m_accept_sock = ret; return 0; } else if (errno != EADDRINUSE) { return -1; } if (m_transfer_fname.empty()) { return -1; } Logger::Info("takeover: beginning listen socket acquisition"); uint8_t fd_request[3] = P_VERSION C_FD_REQ; uint8_t fd_response[3] = {0,0,0}; uint32_t response_len = sizeof(fd_response); afdt_error_t err = AFDT_ERROR_T_INIT; // TODO(dreiss): Make this timeout configurable. struct timeval timeout = { 2 , 0 }; ret = afdt_sync_client( m_transfer_fname.c_str(), fd_request, sizeof(fd_request) - 1, fd_response, &response_len, &m_accept_sock, &timeout, &err); if (ret < 0) { fd_transfer_error_hander(&err, nullptr); errno = EADDRINUSE; return -1; } else if (m_accept_sock < 0) { String resp((const char*)fd_response, response_len, CopyString); Logger::Error( "AFDT did not receive a file descriptor: " "response = '%s'", f_addcslashes(resp, null_string).data()); errno = EADDRINUSE; return -1; } Logger::Info("takeover: acquired listen socket"); m_took_over = true; ret = evhttp_accept_socket(m_server, m_accept_sock); if (ret < 0) { Logger::Error("evhttp_accept_socket: %s", folly::errnoStr(errno).c_str()); int errno_save = errno; close(m_accept_sock); m_accept_sock = -1; errno = errno_save; return -1; } return 0; }