Skip to content

Commit

Permalink
Cleaned up socket exception handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
gunnarbeutner committed Jul 17, 2012
1 parent a224c20 commit 0ad6026
Show file tree
Hide file tree
Showing 40 changed files with 178 additions and 198 deletions.
24 changes: 12 additions & 12 deletions base/application.cpp
Expand Up @@ -39,7 +39,7 @@ Application::Application(void)
#ifdef _WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
throw Win32Exception("WSAStartup failed", WSAGetLastError());
throw_exception(Win32Exception("WSAStartup failed", WSAGetLastError()));
#else /* _WIN32 */
lt_dlinit();
#endif /* _WIN32 */
Expand Down Expand Up @@ -133,12 +133,12 @@ Component::Ptr Application::LoadComponent(const string& path,
HMODULE hModule = LoadLibrary(path.c_str());

if (hModule == NULL)
throw Win32Exception("LoadLibrary('" + path + "') failed", GetLastError());
throw_exception(Win32Exception("LoadLibrary('" + path + "') failed", GetLastError()));
#else /* _WIN32 */
lt_dlhandle hModule = lt_dlopen(path.c_str());

if (hModule == NULL) {
throw runtime_error("Could not load module '" + path + "': " + lt_dlerror());
throw_exception(runtime_error("Could not load module '" + path + "': " + lt_dlerror()));
}
#endif /* _WIN32 */

Expand All @@ -155,8 +155,8 @@ Component::Ptr Application::LoadComponent(const string& path,
#endif /* _WIN32 */

if (pCreateComponent == NULL)
throw runtime_error("Loadable module does not contain "
"CreateComponent function");
throw_exception(runtime_error("Loadable module does not contain "
"CreateComponent function"));

component = Component::Ptr(pCreateComponent());
component->SetConfig(componentConfig);
Expand Down Expand Up @@ -228,7 +228,7 @@ string Application::GetExePath(void) const

char buffer[MAXPATHLEN];
if (getcwd(buffer, sizeof(buffer)) == NULL)
throw PosixException("getcwd failed", errno);
throw_exception(PosixException("getcwd failed", errno));
string workingDirectory = buffer;

if (argv0[0] != '/')
Expand All @@ -255,20 +255,20 @@ string Application::GetExePath(void) const

if (!foundPath) {
executablePath.clear();
throw runtime_error("Could not determine executable path.");
throw_exception(runtime_error("Could not determine executable path."));
}
}
}

if (realpath(executablePath.c_str(), buffer) == NULL)
throw PosixException("realpath failed", errno);
throw_exception(PosixException("realpath failed", errno));

result = buffer;
#else /* _WIN32 */
char FullExePath[MAXPATHLEN];

if (!GetModuleFileName(NULL, FullExePath, sizeof(FullExePath)))
throw Win32Exception("GetModuleFileName() failed", GetLastError());
throw_exception(Win32Exception("GetModuleFileName() failed", GetLastError()));

result = FullExePath;
#endif /* _WIN32 */
Expand Down Expand Up @@ -410,15 +410,15 @@ void Application::UpdatePidFile(const string& filename)
m_PidFile = fopen(filename.c_str(), "w");

if (m_PidFile == NULL)
throw runtime_error("Could not open PID file '" + filename + "'");
throw_exception(runtime_error("Could not open PID file '" + filename + "'"));

#ifndef _WIN32
if (flock(fileno(m_PidFile), LOCK_EX | LOCK_NB) < 0) {
ClosePidFile();

throw runtime_error("Another instance of the application is "
throw_exception(runtime_error("Another instance of the application is "
"already running. Remove the '" + filename + "' file if "
"you're certain that this is not the case.");
"you're certain that this is not the case."));
}
#endif /* _WIN32 */

Expand Down
6 changes: 3 additions & 3 deletions base/asynctask.h
Expand Up @@ -83,13 +83,13 @@ class AsyncTask : public Object
TResult GetResult(void)
{
if (!m_Finished)
throw runtime_error("GetResult called on an unfinished AsyncTask");
throw_exception(runtime_error("GetResult called on an unfinished AsyncTask"));

if (m_ResultRetrieved)
throw runtime_error("GetResult called on an AsyncTask whose result was already retrieved.");
throw_exception(runtime_error("GetResult called on an AsyncTask whose result was already retrieved."));

if (m_Exception)
boost::rethrow_exception(m_Exception);
rethrow_exception(m_Exception);

m_ResultRetrieved = true;

Expand Down
2 changes: 1 addition & 1 deletion base/configobject.cpp
Expand Up @@ -208,7 +208,7 @@ ScriptTask::Ptr ConfigObject::InvokeMethod(const string& method,
ScriptFunction::Ptr func = ScriptFunction::GetByName(funcName);

if (!func)
throw invalid_argument("Function '" + funcName + "' does not exist.");
throw_exception(invalid_argument("Function '" + funcName + "' does not exist."));

ScriptTask::Ptr task = boost::make_shared<ScriptTask>(func, arguments);
task->Start(callback);
Expand Down
2 changes: 1 addition & 1 deletion base/fifo.cpp
Expand Up @@ -57,7 +57,7 @@ void FIFO::ResizeBuffer(size_t newSize)
char *newBuffer = (char *)realloc(m_Buffer, newSize);

if (newBuffer == NULL)
throw bad_alloc();
throw_exception(bad_alloc());

m_Buffer = newBuffer;

Expand Down
4 changes: 4 additions & 0 deletions base/i2-base.h
Expand Up @@ -104,6 +104,7 @@ using std::ostream;
using std::ofstream;

using std::exception;
using std::bad_alloc;
using std::bad_cast;
using std::runtime_error;
using std::logic_error;
Expand Down Expand Up @@ -137,6 +138,9 @@ using boost::mutex;
using boost::condition_variable;
using boost::system_time;
using boost::tie;
using boost::throw_exception;
using boost::rethrow_exception;
using boost::current_exception;

namespace tuples = boost::tuples;

Expand Down
4 changes: 2 additions & 2 deletions base/logger.cpp
Expand Up @@ -111,7 +111,7 @@ string Logger::SeverityToString(LogSeverity severity)
case LogCritical:
return "critical";
default:
throw invalid_argument("Invalid severity.");
throw_exception(invalid_argument("Invalid severity."));
}
}

Expand All @@ -126,5 +126,5 @@ LogSeverity Logger::StringToSeverity(const string& severity)
else if (severity == "critical")
return LogCritical;
else
throw invalid_argument("Invalid severity: " + severity);
throw_exception(invalid_argument("Invalid severity: " + severity));
}
2 changes: 1 addition & 1 deletion base/process.cpp
Expand Up @@ -150,7 +150,7 @@ void Process::InitTask(void)
#endif /* _MSC_VER */

if (m_FP == NULL)
throw runtime_error("Could not create process.");
throw_exception(runtime_error("Could not create process."));
}

bool Process::RunTask(void)
Expand Down
95 changes: 45 additions & 50 deletions base/socket.cpp
Expand Up @@ -62,10 +62,10 @@ void Socket::SetFD(SOCKET fd)
int flags;
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
throw PosixException("fcntl failed", errno);
throw_exception(PosixException("fcntl failed", errno));

if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
throw PosixException("fcntl failed", errno);
throw_exception(PosixException("fcntl failed", errno));
#else /* F_GETFL */
unsigned long lTrue = 1;
ioctlsocket(fd, FIONBIO, &lTrue);
Expand Down Expand Up @@ -105,6 +105,8 @@ void Socket::CloseInternal(bool from_dtor)
if (m_FD == INVALID_SOCKET)
return;

SetConnected(false);

closesocket(m_FD);
m_FD = INVALID_SOCKET;

Expand Down Expand Up @@ -146,30 +148,12 @@ int Socket::GetLastSocketError(void)
#endif /* _WIN32 */
}

/**
* Handles a socket error by calling the OnError event or throwing an exception
* when there are no observers for the OnError event.
*
* @param ex An exception.
*/
void Socket::HandleSocketError(const exception& ex)
{
if (!OnError.empty()) {
Event::Post(boost::bind(boost::ref(OnError), GetSelf(), runtime_error(ex.what())));

CloseInternal(false);
} else {
throw ex;
}
}

/**
* Processes errors that have occured for the socket.
*/
void Socket::HandleException(void)
{
HandleSocketError(SocketException(
"select() returned fd in except fdset", GetError()));
throw_exception(SocketException("select() returned fd in except fdset", GetError()));
}

/**
Expand Down Expand Up @@ -208,9 +192,10 @@ string Socket::GetAddressFromSockaddr(sockaddr *address, socklen_t len)
char host[NI_MAXHOST];
char service[NI_MAXSERV];

if (getnameinfo(address, len, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
throw SocketException("getnameinfo() failed",
GetLastSocketError());
if (getnameinfo(address, len, host, sizeof(host), service,
sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
throw_exception(SocketException("getnameinfo() failed",
GetLastSocketError()));

stringstream s;
s << "[" << host << "]:" << service;
Expand All @@ -229,12 +214,8 @@ string Socket::GetClientAddress(void)
sockaddr_storage sin;
socklen_t len = sizeof(sin);

if (getsockname(GetFD(), (sockaddr *)&sin, &len) < 0) {
HandleSocketError(SocketException(
"getsockname() failed", GetError()));

return string();
}
if (getsockname(GetFD(), (sockaddr *)&sin, &len) < 0)
throw_exception(SocketException("getsockname() failed", GetError()));

return GetAddressFromSockaddr((sockaddr *)&sin, len);
}
Expand All @@ -251,12 +232,8 @@ string Socket::GetPeerAddress(void)
sockaddr_storage sin;
socklen_t len = sizeof(sin);

if (getpeername(GetFD(), (sockaddr *)&sin, &len) < 0) {
HandleSocketError(SocketException(
"getpeername() failed", GetError()));

return string();
}
if (getpeername(GetFD(), (sockaddr *)&sin, &len) < 0)
throw_exception(SocketException("getpeername() failed", GetError()));

return GetAddressFromSockaddr((sockaddr *)&sin, len);
}
Expand Down Expand Up @@ -311,16 +288,22 @@ void Socket::ReadThreadProc(void)
if (GetFD() == INVALID_SOCKET)
return;

if (rc < 0) {
HandleSocketError(SocketException("select() failed", GetError()));
return;
}
try {
if (rc < 0)
throw_exception(SocketException("select() failed", GetError()));

if (FD_ISSET(fd, &readfds))
HandleReadable();
if (FD_ISSET(fd, &readfds))
HandleReadable();

if (FD_ISSET(fd, &exceptfds))
HandleException();
if (FD_ISSET(fd, &exceptfds))
HandleException();
} catch (const exception&) {
m_Exception = boost::current_exception();

CloseInternal(false);

break;
}

if (WantsToWrite())
m_WriteCV.notify_all(); /* notify Write thread */
Expand Down Expand Up @@ -359,13 +342,19 @@ void Socket::WriteThreadProc(void)
if (GetFD() == INVALID_SOCKET)
return;

if (rc < 0) {
HandleSocketError(SocketException("select() failed", GetError()));
return;
}
try {
if (rc < 0)
throw_exception(SocketException("select() failed", GetError()));

if (FD_ISSET(fd, &writefds))
HandleWritable();
if (FD_ISSET(fd, &writefds))
HandleWritable();
} catch (const exception&) {
m_Exception = boost::current_exception();

CloseInternal(false);

break;
}
}
}

Expand All @@ -383,3 +372,9 @@ bool Socket::IsConnected(void) const
{
return m_Connected;
}

void Socket::CheckException(void)
{
if (m_Exception)
rethrow_exception(m_Exception);
}
12 changes: 7 additions & 5 deletions base/socket.h
Expand Up @@ -35,7 +35,6 @@ class I2_BASE_API Socket : public Object

~Socket(void);

boost::signal<void (const Socket::Ptr&, const exception&)> OnError;
boost::signal<void (const Socket::Ptr&)> OnClosed;

virtual void Start(void);
Expand All @@ -47,18 +46,20 @@ class I2_BASE_API Socket : public Object

mutex& GetMutex(void) const;

bool IsConnected(void) const;

void CheckException(void);

protected:
Socket(void);

void SetFD(SOCKET fd);
SOCKET GetFD(void) const;

void SetConnected(bool connected);
bool IsConnected(void) const;

int GetError(void) const;
static int GetLastSocketError(void);
void HandleSocketError(const exception& ex);

virtual bool WantsToRead(void) const;
virtual bool WantsToWrite(void) const;
Expand All @@ -69,8 +70,6 @@ class I2_BASE_API Socket : public Object

virtual void CloseInternal(bool from_dtor);

mutable mutex m_Mutex;

private:
SOCKET m_FD; /**< The socket descriptor. */
bool m_Connected;
Expand All @@ -80,6 +79,9 @@ class I2_BASE_API Socket : public Object

condition_variable m_WriteCV;

mutable mutex m_Mutex;
boost::exception_ptr m_Exception;

void ReadThreadProc(void);
void WriteThreadProc(void);

Expand Down
2 changes: 1 addition & 1 deletion base/streamlogger.cpp
Expand Up @@ -38,7 +38,7 @@ void StreamLogger::OpenFile(const string& filename)
stream->open(filename.c_str(), ofstream::out | ofstream::trunc);

if (!stream->good())
throw runtime_error("Could not open logfile '" + filename + "'");
throw_exception(runtime_error("Could not open logfile '" + filename + "'"));
} catch (const exception&) {
delete stream;
throw;
Expand Down

0 comments on commit 0ad6026

Please sign in to comment.