Skip to content

Commit 13aa830

Browse files
committed
Fix async in sync error when a VM calls Com_Error
1 parent 93521a7 commit 13aa830

File tree

6 files changed

+27
-9
lines changed

6 files changed

+27
-9
lines changed

src/common/IPC.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,11 @@ class Channel {
547547
Channel(Socket socket)
548548
: socket(std::move(socket)), counter(0) {}
549549
Channel(Channel&& other)
550-
: socket(std::move(other.socket)) {}
550+
: socket(std::move(other.socket)), handlingAsyncMsg(other.handlingAsyncMsg) {}
551551
Channel& operator=(Channel&& other)
552552
{
553553
std::swap(socket, other.socket);
554+
handlingAsyncMsg = other.handlingAsyncMsg;
554555
return *this;
555556
}
556557
explicit operator bool() const

src/engine/client/cl_cgame.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1564,7 +1564,10 @@ void CGameVM::CGameInit(int serverMessageNum, int serverCommandSequence, int cli
15641564

15651565
void CGameVM::CGameShutdown()
15661566
{
1567-
this->SendMsg<CGameShutdownMsg>();
1567+
if (!services->HasVMErrored()) {
1568+
this->SendMsg<CGameShutdownMsg>();
1569+
}
1570+
this->Free();
15681571
services = nullptr;
15691572
}
15701573

src/engine/framework/CommonVMServices.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ namespace VM {
222222

223223
case QVM_COMMON_ERROR:
224224
IPC::HandleMsg<ErrorMsg>(channel, std::move(reader), [this](std::string text) {
225+
vmErrored = true;
225226
Com_Error(ERR_DROP, "%s", text.c_str());
226227
});
227228
break;
@@ -353,7 +354,7 @@ namespace VM {
353354
// Misc, Dispatch
354355

355356
CommonVMServices::CommonVMServices(VMBase& vm, Str::StringRef vmName, int commandFlag)
356-
:vmName(vmName), vm(vm), commandFlag(commandFlag), commandProxy(new ProxyCmd(*this, commandFlag)) {
357+
:vmName(vmName), vm(vm), vmErrored(false), commandProxy(new ProxyCmd(*this, commandFlag)) {
357358
}
358359

359360
CommonVMServices::~CommonVMServices() {
@@ -389,6 +390,10 @@ namespace VM {
389390
}
390391
}
391392

393+
bool CommonVMServices::HasVMErrored() const {
394+
return vmErrored;
395+
}
396+
392397
VMBase& CommonVMServices::GetVM() {
393398
return vm;
394399
}

src/engine/framework/CommonVMServices.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ namespace VM {
4444

4545
void Syscall(int major, int minor, IPC::Reader reader, IPC::Channel& channel);
4646

47+
bool HasVMErrored() const;
48+
4749
private:
4850
std::string vmName;
4951
VMBase& vm;
52+
bool vmErrored;
5053

5154
VMBase& GetVM();
5255

src/engine/server/server.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ class GameVM: public VM::VMBase {
334334

335335
IPC::SharedMemory shmRegion;
336336

337-
VM::CommonVMServices services;
337+
std::unique_ptr<VM::CommonVMServices> services;
338338
};
339339

340340
//=============================================================================

src/engine/server/sv_game.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -437,16 +437,18 @@ qboolean SV_GetTag( int clientNum, int tagFileNumber, const char *tagname, orien
437437
#endif
438438
}
439439

440-
GameVM::GameVM(): VM::VMBase("game"), services(*this, "Game", Cmd::GAME_VM)
441-
{
440+
GameVM::GameVM(): VM::VMBase("game"), services(nullptr){
442441
}
443442

444443
void GameVM::Start()
445444
{
445+
services = std::unique_ptr<VM::CommonVMServices>(new VM::CommonVMServices(*this, "Game", Cmd::GAME_VM));
446+
446447
uint32_t version = this->Create();
447448
if ( version != GAME_API_VERSION ) {
448449
Com_Error( ERR_DROP, "Game ABI mismatch, expected %d, got %d", GAME_API_VERSION, version );
449450
}
451+
450452
this->GameStaticInit();
451453
}
452454

@@ -462,8 +464,12 @@ void GameVM::GameInit(int levelTime, int randomSeed, qboolean restart)
462464

463465
void GameVM::GameShutdown(qboolean restart)
464466
{
465-
//TODO ignore errors
466-
this->SendMsg<GameShutdownMsg>(restart);
467+
if (!services->HasVMErrored()) {
468+
this->SendMsg<GameShutdownMsg>(restart);
469+
} else {
470+
this->Free();
471+
services = nullptr;
472+
}
467473

468474
// Release the shared memory region
469475
this->shmRegion.Close();
@@ -534,7 +540,7 @@ void GameVM::Syscall(uint32_t id, IPC::Reader reader, IPC::Channel& channel)
534540
this->QVMSyscall(minor, reader, channel);
535541

536542
} else if (major < VM::LAST_COMMON_SYSCALL) {
537-
services.Syscall(major, minor, std::move(reader), channel);
543+
services->Syscall(major, minor, std::move(reader), channel);
538544

539545
} else {
540546
Com_Error(ERR_DROP, "Bad major game syscall number: %d", major);

0 commit comments

Comments
 (0)