diff options
author | Perttu Ahola <celeron55@gmail.com> | 2012-03-11 20:45:43 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2012-03-11 20:45:43 +0200 |
commit | 618314985d6a632ccfd2001d969d32a5ee6e4ca1 (patch) | |
tree | 94faf77b08206466fb55f80448b02c557e734881 | |
parent | d1d83d7e7f5e2e7cbef5272eda9c580129e301a3 (diff) | |
download | minetest-618314985d6a632ccfd2001d969d32a5ee6e4ca1.tar.gz minetest-618314985d6a632ccfd2001d969d32a5ee6e4ca1.tar.bz2 minetest-618314985d6a632ccfd2001d969d32a5ee6e4ca1.zip |
Proper handling of failing to bind server socket
-rw-r--r-- | src/connection.cpp | 15 | ||||
-rw-r--r-- | src/connection.h | 15 | ||||
-rw-r--r-- | src/server.cpp | 15 | ||||
-rw-r--r-- | src/server.h | 8 |
4 files changed, 51 insertions, 2 deletions
diff --git a/src/connection.cpp b/src/connection.cpp index 60c99dc73..58a0fb2bd 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -986,8 +986,16 @@ nextpeer: void Connection::serve(u16 port) { dout_con<<getDesc()<<" serving at port "<<port<<std::endl; - m_socket.Bind(port); - m_peer_id = PEER_ID_SERVER; + try{ + m_socket.Bind(port); + m_peer_id = PEER_ID_SERVER; + } + catch(SocketException &e){ + // Create event + ConnectionEvent e; + e.bindFailed(); + putEvent(e); + } } void Connection::connect(Address address) @@ -1597,6 +1605,9 @@ u32 Connection::Receive(u16 &peer_id, SharedBuffer<u8> &data) if(m_bc_peerhandler) m_bc_peerhandler->deletingPeer(&tmp, e.timeout); continue; } + case CONNEVENT_BIND_FAILED: + throw ConnectionBindFailed("Failed to bind socket " + "(port already in use?)"); } } throw NoIncomingDataException("No incoming data"); diff --git a/src/connection.h b/src/connection.h index 6d26e2e35..b793f580f 100644 --- a/src/connection.h +++ b/src/connection.h @@ -59,6 +59,14 @@ public: {} }; +class ConnectionBindFailed : public BaseException +{ +public: + ConnectionBindFailed(const char *s): + BaseException(s) + {} +}; + /*class ThrottlingException : public BaseException { public: @@ -424,6 +432,7 @@ enum ConnectionEventType{ CONNEVENT_DATA_RECEIVED, CONNEVENT_PEER_ADDED, CONNEVENT_PEER_REMOVED, + CONNEVENT_BIND_FAILED, }; struct ConnectionEvent @@ -447,6 +456,8 @@ struct ConnectionEvent return "CONNEVENT_PEER_ADDED"; case CONNEVENT_PEER_REMOVED: return "CONNEVENT_PEER_REMOVED"; + case CONNEVENT_BIND_FAILED: + return "CONNEVENT_BIND_FAILED"; } return "Invalid ConnectionEvent"; } @@ -470,6 +481,10 @@ struct ConnectionEvent timeout = timeout_; address = address_; } + void bindFailed() + { + type = CONNEVENT_BIND_FAILED; + } }; enum ConnectionCommandType{ diff --git a/src/server.cpp b/src/server.cpp index 767de035f..63bf794ab 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -109,6 +109,10 @@ void * ServerThread::Thread() { infostream<<"Server: PeerNotFoundException"<<std::endl; } + catch(con::ConnectionBindFailed &e) + { + m_server->setAsyncFatalError(e.what()); + } } END_DEBUG_EXCEPTION_HANDLER(errorstream) @@ -837,6 +841,7 @@ Server::Server( m_path_world(path_world), m_path_config(path_config), m_gamespec(gamespec), + m_async_fatal_error(""), m_env(NULL), m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this), m_authmanager(path_world+DIR_DELIM+"auth.txt"), @@ -865,6 +870,9 @@ Server::Server( m_step_dtime_mutex.Init(); m_step_dtime = 0.0; + if(path_world == "") + throw ServerError("Supplied empty world path"); + if(!gamespec.isValid()) throw ServerError("Supplied invalid gamespec"); @@ -1079,6 +1087,8 @@ Server::~Server() void Server::start(unsigned short port) { DSTACK(__FUNCTION_NAME); + infostream<<"Starting server on port "<<port<<"..."<<std::endl; + // Stop thread if already running m_thread.stop(); @@ -1128,6 +1138,11 @@ void Server::step(float dtime) JMutexAutoLock lock(m_step_dtime_mutex); m_step_dtime += dtime; } + // Throw if fatal error occurred in thread + std::string async_err = m_async_fatal_error.get(); + if(async_err != ""){ + throw ServerError(async_err); + } } void Server::AsyncRunStep() diff --git a/src/server.h b/src/server.h index 4948b8ba1..0b4c67deb 100644 --- a/src/server.h +++ b/src/server.h @@ -545,6 +545,11 @@ public: std::string getWorldPath(){ return m_path_world; } + void setAsyncFatalError(const std::string &error) + { + m_async_fatal_error.set(error); + } + private: // con::PeerHandler implementation. @@ -658,6 +663,9 @@ private: // Equivalent of /usr/share/minetest/server std::string m_path_share; + // Thread can set; step() will throw as ServerError + MutexedVariable<std::string> m_async_fatal_error; + // Some timers float m_liquid_transform_timer; float m_print_info_timer; |