aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2012-03-11 20:45:43 +0200
committerPerttu Ahola <celeron55@gmail.com>2012-03-11 20:45:43 +0200
commit618314985d6a632ccfd2001d969d32a5ee6e4ca1 (patch)
tree94faf77b08206466fb55f80448b02c557e734881 /src
parentd1d83d7e7f5e2e7cbef5272eda9c580129e301a3 (diff)
downloadminetest-618314985d6a632ccfd2001d969d32a5ee6e4ca1.tar.gz
minetest-618314985d6a632ccfd2001d969d32a5ee6e4ca1.tar.bz2
minetest-618314985d6a632ccfd2001d969d32a5ee6e4ca1.zip
Proper handling of failing to bind server socket
Diffstat (limited to 'src')
-rw-r--r--src/connection.cpp15
-rw-r--r--src/connection.h15
-rw-r--r--src/server.cpp15
-rw-r--r--src/server.h8
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;