| 109 | } |
| 110 | |
| 111 | Status ThriftServer::ThriftServerEventProcessor::StartAndWaitForServer() { |
| 112 | // Locking here protects against missed notifications if Supervise executes quickly |
| 113 | unique_lock<mutex> lock(signal_lock_); |
| 114 | thrift_server_->started_ = false; |
| 115 | |
| 116 | stringstream name; |
| 117 | name << "supervise-" << thrift_server_->name_; |
| 118 | RETURN_IF_ERROR(Thread::Create("thrift-server", name.str(), |
| 119 | &ThriftServer::ThriftServerEventProcessor::Supervise, this, |
| 120 | &thrift_server_->server_thread_)); |
| 121 | |
| 122 | timespec deadline; |
| 123 | TimeFromNowMillis(ThriftServer::ThriftServerEventProcessor::TIMEOUT_MS, &deadline); |
| 124 | |
| 125 | // Loop protects against spurious wakeup. Locks provide necessary fences to ensure |
| 126 | // visibility. |
| 127 | while (!signal_fired_) { |
| 128 | // Yields lock and allows supervision thread to continue and signal |
| 129 | if (!signal_cond_.WaitUntil(lock, deadline)) { |
| 130 | stringstream ss; |
| 131 | ss << "ThriftServer '" << thrift_server_->name_ << "' (on port: " |
| 132 | << thrift_server_->port_ << ") did not start within " |
| 133 | << ThriftServer::ThriftServerEventProcessor::TIMEOUT_MS << "ms"; |
| 134 | LOG(ERROR) << ss.str(); |
| 135 | return Status(ss.str()); |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | // started_ == true only if preServe was called. May be false if there was an exception |
| 140 | // after preServe that was caught by Supervise, causing it to reset the error condition. |
| 141 | if (thrift_server_->started_ == false) { |
| 142 | stringstream ss; |
| 143 | ss << "ThriftServer '" << thrift_server_->name_ << "' (on port: " |
| 144 | << thrift_server_->port_ << ") did not start correctly "; |
| 145 | LOG(ERROR) << ss.str(); |
| 146 | return Status(ss.str()); |
| 147 | } |
| 148 | return Status::OK(); |
| 149 | } |
| 150 | |
| 151 | void ThriftServer::ThriftServerEventProcessor::Supervise() { |
| 152 | DCHECK(thrift_server_->server_.get() != NULL); |