Skip to content

Commit

Permalink
Prevent sending sync messages in VM toplevel
Browse files Browse the repository at this point in the history
  • Loading branch information
Kangz committed Feb 12, 2015
1 parent d251cf1 commit 21047ac
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 15 deletions.
34 changes: 24 additions & 10 deletions src/common/IPC/Channel.h
Expand Up @@ -75,18 +75,25 @@ namespace IPC {
* send it in the socket.
*/

#ifdef BUILD_ENGINE
static const bool TOPLEVEL_MSG_ALLOWED = true;
#else
static const bool TOPLEVEL_MSG_ALLOWED = false;
#endif

class Channel {
public:
Channel()
: handlingAsyncMsg(false) {}
: canSendSyncMsg(TOPLEVEL_MSG_ALLOWED), canSendAsyncMsg(TOPLEVEL_MSG_ALLOWED) {}
Channel(Socket socket)
: socket(std::move(socket)), handlingAsyncMsg(false) {}
: socket(std::move(socket)), canSendSyncMsg(TOPLEVEL_MSG_ALLOWED), canSendAsyncMsg(TOPLEVEL_MSG_ALLOWED) {}
Channel(Channel&& other)
: socket(std::move(other.socket)), handlingAsyncMsg(false) {}
: socket(std::move(other.socket)), canSendSyncMsg(TOPLEVEL_MSG_ALLOWED), canSendAsyncMsg(TOPLEVEL_MSG_ALLOWED) {}
Channel& operator=(Channel&& other)
{
std::swap(socket, other.socket);
handlingAsyncMsg = other.handlingAsyncMsg;
canSendSyncMsg = other.canSendSyncMsg;
canSendAsyncMsg = other.canSendAsyncMsg;
return *this;
}
explicit operator bool() const
Expand Down Expand Up @@ -122,7 +129,8 @@ namespace IPC {
std::unordered_map<uint32_t, Util::Reader> replies;

public:
bool handlingAsyncMsg;
bool canSendSyncMsg;
bool canSendAsyncMsg;
};

namespace detail {
Expand All @@ -133,6 +141,9 @@ namespace IPC {
typedef Message<Id, MsgArgs...> Message;
static_assert(sizeof...(Args) == std::tuple_size<typename Message::Inputs>::value, "Incorrect number of arguments for IPC::SendMsg");

if (channel.canSendAsyncMsg)
Com_Error(ERR_DROP, "Attempting to send a Message in VM toplevel");

Util::Writer writer;
writer.Write<uint32_t>(Message::id);
writer.WriteArgs(Util::TypeListFromTuple<typename Message::Inputs>(), std::forward<Args>(args)...);
Expand All @@ -143,8 +154,8 @@ namespace IPC {
typedef SyncMessage<Msg, Reply> Message;
static_assert(sizeof...(Args) == std::tuple_size<typename Message::Inputs>::value + std::tuple_size<typename Message::Outputs>::value, "Incorrect number of arguments for IPC::SendMsg");

if (channel.handlingAsyncMsg)
Com_Error(ERR_DROP, "Attempting to send a SyncMessage while handling a Message");
if (channel.canSendSyncMsg)
Com_Error(ERR_DROP, "Attempting to send a SyncMessage while handling a Message or in VM toplevel");

Util::Writer writer;
writer.Write<uint32_t>(Message::id);
Expand Down Expand Up @@ -181,10 +192,13 @@ namespace IPC {
typename MapTuple<typename Message::Inputs>::type inputs;
reader.FillTuple<0>(Util::TypeListFromTuple<typename Message::Inputs>(), inputs);

bool old = channel.handlingAsyncMsg;
channel.handlingAsyncMsg = true;
bool oldSync = channel.canSendSyncMsg;
bool oldAsync = channel.canSendAsyncMsg;
channel.canSendSyncMsg = false;
channel.canSendAsyncMsg = true;
Util::apply(std::forward<Func>(func), std::move(inputs));
channel.handlingAsyncMsg = old;
channel.canSendSyncMsg = oldSync;
channel.canSendAsyncMsg = oldAsync;
}
template<typename Func, typename Msg, typename Reply> void HandleMsg(Channel& channel, SyncMessage<Msg, Reply>, Util::Reader reader, Func&& func)
{
Expand Down
8 changes: 4 additions & 4 deletions src/gamelogic/shared/CommandBufferClient.cpp
Expand Up @@ -57,8 +57,8 @@ namespace IPC {
return;
}

if (VM::rootChannel.handlingAsyncMsg) {
Sys::Drop("Trying to Flush the %s command buffer when handling an async message", name);
if (!VM::rootChannel.canSendSyncMsg) {
Sys::Drop("Trying to Flush the %s command buffer when handling an async message or in toplevel", name);
}

buffer.LoadReaderData();
Expand All @@ -69,8 +69,8 @@ namespace IPC {
}

void CommandBufferClient::Write(Util::Writer& writer) {
if (VM::rootChannel.handlingAsyncMsg) {
Sys::Drop("Trying to write to the %s command buffer when handling an async message", name);
if (!VM::rootChannel.canSendSyncMsg) {
Sys::Drop("Trying to write to the %s command buffer when handling an async message or in toplevel", name);
}
auto& writerData = writer.GetData();
uint32_t dataSize = writerData.size();
Expand Down
2 changes: 1 addition & 1 deletion src/gamelogic/shared/VMMain.cpp
Expand Up @@ -71,7 +71,7 @@ void Sys::Error(Str::StringRef message)
if (!errorEntered.test_and_set()) {
// Disable checks for sending sync messages when handling async messages.
// At this point we don't really care since this is an error.
VM::rootChannel.handlingAsyncMsg = false;
VM::rootChannel.canSendSyncMsg = true;

// Try to tell the engine about the error, but ignore errors doing so.
try {
Expand Down

0 comments on commit 21047ac

Please sign in to comment.