Future<Nothing> HealthCheckerProcess::_tcpHealthCheck() { CHECK_EQ(HealthCheck::TCP, check.type()); CHECK(check.has_tcp()); // TCP_CHECK_COMMAND should be reachable. CHECK(os::exists(launcherDir)); const HealthCheck::TCPCheckInfo& tcp = check.tcp(); VLOG(1) << "Launching TCP health check at port '" << tcp.port() << "'"; const string tcpConnectPath = path::join(launcherDir, TCP_CHECK_COMMAND); const vector<string> tcpConnectArguments = { tcpConnectPath, "--ip=" + DEFAULT_DOMAIN, "--port=" + stringify(tcp.port()) }; Try<Subprocess> s = subprocess( tcpConnectPath, tcpConnectArguments, Subprocess::PATH("/dev/null"), Subprocess::PIPE(), Subprocess::PIPE(), nullptr, None(), clone); if (s.isError()) { return Failure( "Failed to create the " + string(TCP_CHECK_COMMAND) + " subprocess: " + s.error()); } pid_t tcpConnectPid = s->pid(); Duration timeout = Seconds(static_cast<int64_t>(check.timeout_seconds())); return await( s->status(), process::io::read(s->out().get()), process::io::read(s->err().get())) .after(timeout, [timeout, tcpConnectPid](Future<tuple<Future<Option<int>>, Future<string>, Future<string>>> future) { future.discard(); if (tcpConnectPid != -1) { // Cleanup the TCP_CHECK_COMMAND process. VLOG(1) << "Killing the TCP health check process " << tcpConnectPid; os::killtree(tcpConnectPid, SIGKILL); } return Failure( string(TCP_CHECK_COMMAND) + " has not returned after " + stringify(timeout) + "; aborting"); }) .then(defer(self(), &Self::__tcpHealthCheck, lambda::_1)); }
Future<Nothing> HealthCheckerProcess::_httpHealthCheck() { CHECK_EQ(HealthCheck::HTTP, check.type()); CHECK(check.has_http()); const HealthCheck::HTTPCheckInfo& http = check.http(); const string scheme = http.has_scheme() ? http.scheme() : DEFAULT_HTTP_SCHEME; const string path = http.has_path() ? http.path() : ""; const string url = scheme + "://" + DEFAULT_DOMAIN + ":" + stringify(http.port()) + path; VLOG(1) << "Launching HTTP health check '" << url << "'"; const vector<string> argv = { HTTP_CHECK_COMMAND, "-s", // Don't show progress meter or error messages. "-S", // Makes curl show an error message if it fails. "-L", // Follows HTTP 3xx redirects. "-k", // Ignores SSL validation when scheme is https. "-w", "%{http_code}", // Displays HTTP response code on stdout. "-o", "/dev/null", // Ignores output. url }; Try<Subprocess> s = subprocess( HTTP_CHECK_COMMAND, argv, Subprocess::PATH("/dev/null"), Subprocess::PIPE(), Subprocess::PIPE(), nullptr, None(), clone); if (s.isError()) { return Failure( "Failed to create the " + string(HTTP_CHECK_COMMAND) + " subprocess: " + s.error()); } pid_t curlPid = s->pid(); Duration timeout = Seconds(static_cast<int64_t>(check.timeout_seconds())); return await( s->status(), process::io::read(s->out().get()), process::io::read(s->err().get())) .after(timeout, [timeout, curlPid](Future<tuple<Future<Option<int>>, Future<string>, Future<string>>> future) { future.discard(); if (curlPid != -1) { // Cleanup the HTTP_CHECK_COMMAND process. VLOG(1) << "Killing the HTTP health check process " << curlPid; os::killtree(curlPid, SIGKILL); } return Failure( string(HTTP_CHECK_COMMAND) + " has not returned after " + stringify(timeout) + "; aborting"); }) .then(defer(self(), &Self::__httpHealthCheck, lambda::_1)); }