From 67fb75d659b4300088fe3d22e4724e624d2da196 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 18 Mar 2023 08:12:56 -0700 Subject: [PATCH] base,cpu,dev,sim: Pull common logic into ListenSocket::listen(). Create a version of listen() which handles common logic internally, including scanning for an available port number, and notifying what port was chosen. The port is managed internal to ListenSocket, so that the logic interacting with it doesn't need to manually manage a port number, and hence a port number does not need to exist for non AF_INET sockets. Change-Id: Ie371eccc4d0da5e7b90714508e4cb72fb0091875 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/69160 Tested-by: kokoro Reviewed-by: Yu-hsin Wang Maintainer: Gabe Black --- src/base/remote_gdb.cc | 19 ++++++++----------- src/base/remote_gdb.hh | 3 +-- src/base/socket.cc | 23 +++++++++++++++++++++-- src/base/socket.hh | 16 +++++++++++++++- src/base/vnc/vncserver.cc | 16 ++++------------ src/base/vnc/vncserver.hh | 2 +- src/cpu/nativetrace.cc | 10 +++------- src/dev/net/ethertap.cc | 11 +++-------- src/dev/serial/terminal.cc | 18 +++++------------- src/dev/serial/terminal.hh | 2 +- src/sim/workload.cc | 4 ++-- 11 files changed, 64 insertions(+), 60 deletions(-) diff --git a/src/base/remote_gdb.cc b/src/base/remote_gdb.cc index 1a2fef42d8..c8cb32fd71 100644 --- a/src/base/remote_gdb.cc +++ b/src/base/remote_gdb.cc @@ -392,7 +392,7 @@ std::map hardBreakMap; BaseRemoteGDB::BaseRemoteGDB(System *_system, int _port) : incomingConnectionEvent(nullptr), incomingDataEvent(nullptr), - _port(_port), fd(-1), sys(_system), + listener(_system->name() + ".remote_gdb", _port), fd(-1), sys(_system), connectEvent(*this), disconnectEvent(*this), trapEvent(this), singleStepEvent(*this) {} @@ -417,17 +417,14 @@ BaseRemoteGDB::listen() return; } - while (!listener.listen(_port)) { - DPRINTF(GDBMisc, "Can't bind port %d\n", _port); - _port++; - } + listener.listen(); incomingConnectionEvent = new IncomingConnectionEvent(this, listener.getfd(), POLLIN); pollQueue.schedule(incomingConnectionEvent); - ccprintf(std::cerr, "%d: %s: listening for remote gdb on port %d\n", - curTick(), name(), _port); + ccprintf(std::cerr, "%d: %s: listening for remote gdb on %s\n", + curTick(), name(), listener); } void @@ -448,12 +445,12 @@ BaseRemoteGDB::connect() } } -int -BaseRemoteGDB::port() const +const ListenSocket & +BaseRemoteGDB::hostSocket() const { panic_if(!listener.islistening(), - "Remote GDB port is unknown until listen() has been called.\n"); - return _port; + "Remote GDB socket is unknown until listen() has been called."); + return listener; } void diff --git a/src/base/remote_gdb.hh b/src/base/remote_gdb.hh index 80c108ba22..60a0d6a1eb 100644 --- a/src/base/remote_gdb.hh +++ b/src/base/remote_gdb.hh @@ -161,7 +161,7 @@ class BaseRemoteGDB void listen(); void connect(); - int port() const; + const ListenSocket &hostSocket() const; void attach(int fd); void detach(); @@ -232,7 +232,6 @@ class BaseRemoteGDB IncomingDataEvent *incomingDataEvent; ListenSocket listener; - int _port; // The socket commands come in through. int fd; diff --git a/src/base/socket.cc b/src/base/socket.cc index 280f92b593..1aff73a7ff 100644 --- a/src/base/socket.cc +++ b/src/base/socket.cc @@ -173,10 +173,12 @@ ListenSocket::acceptCloexec(int sockfd, struct sockaddr *addr, // // -ListenSocket::ListenSocket() - : listening(false), fd(-1) +ListenSocket::ListenSocket(const std::string &_name, int port) + : Named(_name), listening(false), fd(-1), _port(port) {} +ListenSocket::ListenSocket() : ListenSocket("", -1) {} + ListenSocket::~ListenSocket() { if (fd != -1) @@ -231,6 +233,23 @@ ListenSocket::listen(int port) return true; } +void +ListenSocket::listen() +{ + while (!listen(_port)) { + _port++; + fatal_if(_port > 65536, "%s: cannot find an available port.", name()); + } + ccprintf(std::cerr, "%s: Listening for connections on %s\n", + name(), *this); +} + +void +ListenSocket::output(std::ostream &os) const +{ + os << "port " << _port; +} + // Open a connection. Accept will block, so if you don't want it to, // make sure a connection is ready before you call accept. diff --git a/src/base/socket.hh b/src/base/socket.hh index d2393e9325..7a616bdd49 100644 --- a/src/base/socket.hh +++ b/src/base/socket.hh @@ -35,6 +35,8 @@ #include +#include "base/named.hh" + namespace gem5 { @@ -69,7 +71,7 @@ struct UnixSocketAddr std::string formattedPath; }; -class ListenSocket +class ListenSocket : public Named { protected: /** @@ -90,6 +92,7 @@ class ListenSocket protected: bool listening; int fd; + int _port; /* * cleanup resets the static variables back to their default values. @@ -101,12 +104,16 @@ class ListenSocket * @ingroup api_socket * @{ */ + ListenSocket(const std::string &_name, int port); ListenSocket(); virtual ~ListenSocket(); virtual int accept(); virtual bool listen(int port); + virtual void listen(); + + virtual void output(std::ostream &os) const; int getfd() const { return fd; } bool islistening() const { return listening; } @@ -119,6 +126,13 @@ class ListenSocket /** @} */ // end of api_socket }; +inline static std::ostream & +operator << (std::ostream &os, const ListenSocket &socket) +{ + socket.output(os); + return os; +} + } // namespace gem5 #endif //__SOCKET_HH__ diff --git a/src/base/vnc/vncserver.cc b/src/base/vnc/vncserver.cc index 39a1338799..2d32cef8bb 100644 --- a/src/base/vnc/vncserver.cc +++ b/src/base/vnc/vncserver.cc @@ -117,11 +117,11 @@ VncServer::DataEvent::process(int revent) */ VncServer::VncServer(const Params &p) : VncInput(p), listenEvent(NULL), dataEvent(NULL), number(p.number), - dataFd(-1), sendUpdate(false), + listener(p.name, p.port), sendUpdate(false), supportsRawEnc(false), supportsResizeEnc(false) { if (p.port) - listen(p.port); + listen(); curState = WaitForProtocolVersion; @@ -157,22 +157,14 @@ VncServer::~VncServer() //socket creation and vnc client attach void -VncServer::listen(int port) +VncServer::listen() { if (ListenSocket::allDisabled()) { warn_once("Sockets disabled, not accepting vnc client connections"); return; } - while (!listener.listen(port)) { - DPRINTF(VNC, - "can't bind address vnc server port %d in use PID %d\n", - port, getpid()); - port++; - } - - ccprintf(std::cerr, "%s: Listening for connections on port %d\n", - name(), port); + listener.listen(); listenEvent = new ListenEvent(this, listener.getfd(), POLLIN); pollQueue.schedule(listenEvent); diff --git a/src/base/vnc/vncserver.hh b/src/base/vnc/vncserver.hh index 091cb4d696..7455799025 100644 --- a/src/base/vnc/vncserver.hh +++ b/src/base/vnc/vncserver.hh @@ -182,7 +182,7 @@ class VncServer : public VncInput ListenSocket listener; - void listen(int port); + void listen(); void accept(); void data(); void detach(); diff --git a/src/cpu/nativetrace.cc b/src/cpu/nativetrace.cc index 714787ffa4..05fb41b3a5 100644 --- a/src/cpu/nativetrace.cc +++ b/src/cpu/nativetrace.cc @@ -39,17 +39,13 @@ namespace gem5 namespace trace { NativeTrace::NativeTrace(const Params &p) - : ExeTracer(p) + : ExeTracer(p), native_listener(p.name, 8000) { if (ListenSocket::allDisabled()) fatal("All listeners are disabled!"); - int port = 8000; - while (!native_listener.listen(port)) { - DPRINTF(GDBMisc, "Can't bind port %d\n", port); - port++; - } - ccprintf(std::cerr, "Listening for native process on port %d\n", port); + native_listener.listen(); + fd = native_listener.accept(); } diff --git a/src/dev/net/ethertap.cc b/src/dev/net/ethertap.cc index 0769ad1203..587dba5021 100644 --- a/src/dev/net/ethertap.cc +++ b/src/dev/net/ethertap.cc @@ -240,17 +240,16 @@ class TapListener }; friend class Event; - Event *event; + Event *event = nullptr; void accept(); protected: ListenSocket listener; EtherTapStub *tap; - int port; public: - TapListener(EtherTapStub *t, int p) : event(NULL), tap(t), port(p) {} + TapListener(EtherTapStub *t, int p) : listener(t->name(), p), tap(t) {} ~TapListener() { delete event; } void listen(); @@ -259,12 +258,8 @@ class TapListener void TapListener::listen() { - while (!listener.listen(port)) { - DPRINTF(Ethernet, "TapListener(listen): Can't bind port %d\n", port); - port++; - } + listener.listen(); - ccprintf(std::cerr, "Listening for tap connection on port %d\n", port); event = new Event(this, listener.getfd(), POLLIN|POLLERR); pollQueue.schedule(event); } diff --git a/src/dev/serial/terminal.cc b/src/dev/serial/terminal.cc index 9564876826..02052b5e1a 100644 --- a/src/dev/serial/terminal.cc +++ b/src/dev/serial/terminal.cc @@ -121,8 +121,8 @@ Terminal::DataEvent::process(int revent) */ Terminal::Terminal(const Params &p) : SerialDevice(p), listenEvent(NULL), dataEvent(NULL), - number(p.number), data_fd(-1), txbuf(16384), rxbuf(16384), - outfile(terminalDump(p)) + number(p.number), data_fd(-1), listener(p.name, p.port), + txbuf(16384), rxbuf(16384), outfile(terminalDump(p)) #if TRACING_ON == 1 , linebuf(16384) #endif @@ -131,7 +131,7 @@ Terminal::Terminal(const Params &p) outfile->stream()->setf(std::ios::unitbuf); if (p.port) - listen(p.port); + listen(); } Terminal::~Terminal() @@ -168,22 +168,14 @@ Terminal::terminalDump(const TerminalParams &p) // void -Terminal::listen(int port) +Terminal::listen() { if (ListenSocket::allDisabled()) { warn_once("Sockets disabled, not accepting terminal connections"); return; } - while (!listener.listen(port)) { - DPRINTF(Terminal, - ": can't bind address terminal port %d inuse PID %d\n", - port, getpid()); - port++; - } - - ccprintf(std::cerr, "%s: Listening for connections on port %d\n", - name(), port); + listener.listen(); listenEvent = new ListenEvent(this, listener.getfd(), POLLIN); pollQueue.schedule(listenEvent); diff --git a/src/dev/serial/terminal.hh b/src/dev/serial/terminal.hh index 83ea64b09c..bd6711da8a 100644 --- a/src/dev/serial/terminal.hh +++ b/src/dev/serial/terminal.hh @@ -103,7 +103,7 @@ class Terminal : public SerialDevice protected: ListenSocket listener; - void listen(int port); + void listen(); void accept(); protected: diff --git a/src/sim/workload.cc b/src/sim/workload.cc index ceb1029f77..84b1e40698 100644 --- a/src/sim/workload.cc +++ b/src/sim/workload.cc @@ -97,8 +97,8 @@ Workload::startup() // Now that we're about to start simulation, wait for GDB connections if // requested. if (gdb && waitForRemoteGDB) { - inform("%s: Waiting for a remote GDB connection on port %d.", name(), - gdb->port()); + inform("%s: Waiting for a remote GDB connection on %s.", name(), + gdb->hostSocket()); gdb->connect(); } }