ctrl: register externally started dooms that introduce themselves

TODO: Check on those via kill(pid, 0) or store the last activity time in
DoomState and let dooms time out if they don't send more updates.
This commit is contained in:
oxmox 2023-02-19 12:46:17 +01:00
parent 9e857180be
commit e53023079e

View file

@ -64,6 +64,7 @@ void spawn_doom(ControllerContext &ctx)
// TODO: Close stdin and stdout? Leave them open for now to see the logging // TODO: Close stdin and stdout? Leave them open for now to see the logging
// output. // output.
// FIXME: this doesn't work with SDL :(
if (auto err = posix_spawn(&ds.id, DOOM_EXECUTABLE, nullptr, nullptr, if (auto err = posix_spawn(&ds.id, DOOM_EXECUTABLE, nullptr, nullptr,
const_cast<char *const *>(argv), nullptr)) const_cast<char *const *>(argv), nullptr))
{ {
@ -77,9 +78,8 @@ void spawn_doom(ControllerContext &ctx)
if (!ds.texture) if (!ds.texture)
dp_sdl_fatal("SDL_CreateTexture"); dp_sdl_fatal("SDL_CreateTexture");
ctx.dooms.emplace_back(ds);
log_info("Spawned new doom, pid=%d", ds.id); log_info("Spawned new doom, pid=%d", ds.id);
ctx.dooms.emplace_back(ds);
} }
void end_all_dooms(ControllerContext &ctx) void end_all_dooms(ControllerContext &ctx)
@ -127,6 +127,8 @@ void check_on_dooms(ControllerContext &ctx)
{ {
pid_t pid = 0; pid_t pid = 0;
// This works for dooms forked from the controller, not for externally
// started dooms.
do do
{ {
int wstatus = 0; int wstatus = 0;
@ -153,13 +155,18 @@ void check_on_dooms(ControllerContext &ctx)
void do_networking(ControllerContext &ctx) void do_networking(ControllerContext &ctx)
{ {
// Set to true if we receive at least on DP_DS_Ready DoomState update. Then
// a single DP_DC_RunDoom command is broadcast.
bool sendRunDoom = false; bool sendRunDoom = false;
// Limit the max time we spend doing network stuff.
static const auto MaxNetworkingTime = std::chrono::milliseconds(10);
auto tStart = std::chrono::steady_clock::now(); auto tStart = std::chrono::steady_clock::now();
while (true) while (true)
{ {
if (auto elapsed = std::chrono::steady_clock::now() - tStart; if (auto elapsed = std::chrono::steady_clock::now() - tStart;
elapsed >= std::chrono::milliseconds(10)) elapsed >= MaxNetworkingTime)
{ {
break; break;
} }
@ -179,6 +186,30 @@ void do_networking(ControllerContext &ctx)
{ {
auto msgDoomState = DP_NNG_BODY_AS(msg, MsgDoomState); auto msgDoomState = DP_NNG_BODY_AS(msg, MsgDoomState);
// Check if we know this doom. If it was externally started register
// it in ctx.dooms.
auto pid = msgDoomState->doomId;
auto dit = find_in_container(ctx.dooms, [pid] (const auto &ds) { return ds.id == pid; });
if (dit != std::end(ctx.dooms))
{
dit->state = msgDoomState->doomState;
}
else
{
DoomState ds;
ds.id = pid;
ds.state = msgDoomState->doomState;
ds.texture = SDL_CreateTexture(ctx.renderer, SDL_PIXELFORMAT_RGB888,
SDL_TEXTUREACCESS_STREAMING, DoomScreenWidth, DoomScreenHeight);
if (!ds.texture)
dp_sdl_fatal("SDL_CreateTexture");
log_info("Registered external doom, pid=%d", ds.id);
ctx.dooms.emplace_back(ds);
}
if (msgDoomState->doomState == DP_DS_Ready) if (msgDoomState->doomState == DP_DS_Ready)
sendRunDoom = true; sendRunDoom = true;
} }
@ -193,6 +224,8 @@ void do_networking(ControllerContext &ctx)
auto &ds = *dit; auto &ds = *dit;
SDL_UpdateTexture(ds.texture, nullptr, msgDoomFrame->frame, DoomFramePitch); SDL_UpdateTexture(ds.texture, nullptr, msgDoomFrame->frame, DoomFramePitch);
} }
else
log_warn("Received DoomFrame from unregistered doom, pid=%d", pid);
} }
nng_msg_free(msg); nng_msg_free(msg);