code: private Socket nextSocket() {
      Socket result;
      synchronized (lock) {
        result = nextSocket;
        while (!done && result == null) {
          try {
            lock.wait();
          } catch (InterruptedException e) {
            done = true;
          }
          result = nextSocket;
        }
        nextSocket = null;
      }
  
      if (result != null) {
        // Java InputStream API is blocking by default with no reliable way to stop pending
        // read() call. Setting the timeout to underlying socket will make socket's underlying
        // read() calls throw SocketTimeoutException which unblocks read(). The exception must
        // be properly handled by calling code.
        try {
          // TODO(buck_team): this does not work with current NGUnixDomainSocket
          // implementation
          result.setSoTimeout(this.heartbeatTimeoutMillis);
        } catch (SocketException e) {
          // this exception might be thrown if socket is already closed
          // so we just return null
          return null;
        }
      }
  
      return result;
    }
docs: Returns the next socket to process. This will block the NGSession thread until there's a socket
  to process or the NGSession has been shut down.
  
  @return the next socket to process, or <code>null</code> if the NGSession has been shut down.