[dockyard] Check for port bind errors on startup

SystemMonitorDockyardTest.ServerListening is flaking (see fxb/54034).
Suspecting failure of the gRPC server to bind to the port. This cl
catches that condition and logs it.

TEST: covered by existing tests

Change-Id: Ie57f81923a6bfe8d30f2d2fa1607ec7d14b3aef2
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/404804
Testability-Review: Jeremy Manson <jeremymanson@google.com>
Commit-Queue: Jayson Adams <shrike@google.com>
Reviewed-by: Andy Weiss <dragonbear@google.com>
diff --git a/src/developer/system_monitor/lib/dockyard/dockyard.cc b/src/developer/system_monitor/lib/dockyard/dockyard.cc
index 50e5aa9..c5d7685 100644
--- a/src/developer/system_monitor/lib/dockyard/dockyard.cc
+++ b/src/developer/system_monitor/lib/dockyard/dockyard.cc
@@ -454,7 +454,9 @@
     return false;
   }
   ResetHarvesterData();
-  Initialize();
+  if (!Initialize()) {
+    return false;
+  }
   on_connection_request_ = request;
   on_connection_handler_ = callback;
   server_thread_ = std::thread([this]() { RunGrpcServer(); });
@@ -488,11 +490,11 @@
   }
 }
 
-void Dockyard::Initialize() {
+bool Dockyard::Initialize() {
   std::lock_guard<std::mutex> guard(mutex_);
   if (server_thread_.joinable()) {
     GT_LOG(INFO) << "Dockyard server already initialized";
-    return;
+    return true;
   }
 
   GT_LOG(INFO) << "Starting dockyard server";
@@ -502,16 +504,27 @@
 
   std::string server_address(DEFAULT_SERVER_ADDRESS);
   grpc::ServerBuilder builder;
+  int selected_port = -1;
   // Listen on the given address without any authentication mechanism.
-  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
+  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(),
+                           &selected_port);
   // Register "service" as the instance through which we'll communicate with
   // clients. In this case it corresponds to a *synchronous* service. The
   // builder (and server) will hold a weak pointer to the service.
   builder.RegisterService(protocol_buffer_service_.get());
   // Finally assemble the server.
   std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
+  if (selected_port <= 0) {
+    GT_LOG(ERROR) << "Error binding the gRPC server to the port";
+    return false;
+  } else if (server.get() == nullptr) {
+    // All other start errors are flagged by a null server.
+    GT_LOG(ERROR) << "Error starting the gRPC server";
+    return false;
+  }
   grpc_server_ = std::move(server);
   GT_LOG(INFO) << "Server listening on " << server_address;
+  return true;
 }
 
 void Dockyard::RunGrpcServer() {
diff --git a/src/developer/system_monitor/lib/dockyard/dockyard.h b/src/developer/system_monitor/lib/dockyard/dockyard.h
index 1cec2a1..7bb4cc6 100644
--- a/src/developer/system_monitor/lib/dockyard/dockyard.h
+++ b/src/developer/system_monitor/lib/dockyard/dockyard.h
@@ -680,7 +680,9 @@
                            const std::string& ending);
 
   // Listen for incoming samples.
-  void Initialize();
+  //
+  // Returns |false| on problems with starting the gRPC server.
+  bool Initialize();
 
   // A private version of MatchPaths that expects that a lock has already been
   // acquired.