From 823932af16b0652b0045b51919baef162e90f442 Mon Sep 17 00:00:00 2001 From: oxmox Date: Tue, 14 Feb 2023 23:41:47 +0100 Subject: [PATCH] posix_spawn() doomsims The doomsim startup routine or the controller startup publish are broken. The doomsims never transition from DP_DS_Ready state. --- src/doompanning.cc | 112 +++++++++++++++++++++++++++++++++++++-------- src/doomsim.cc | 6 +++ src/dp_common.h | 1 + src/dp_util.hpp | 11 +++-- 4 files changed, 105 insertions(+), 25 deletions(-) diff --git a/src/doompanning.cc b/src/doompanning.cc index e4a2e3f..0ce2ef6 100644 --- a/src/doompanning.cc +++ b/src/doompanning.cc @@ -4,10 +4,15 @@ #include #include +#include +#include #include #include #include +#include +#include + #include "dp_common.h" #include "dp_util.hpp" @@ -19,10 +24,13 @@ void dp_sdl_fatal(const char *const msg) struct DoomState { - bool alive = false; // FIXME for testing only + doomid_t id; + pid_t pid; + DP_DoomState state = DP_DS_Unknown; }; -static_assert(std::is_trivially_copyable::value, "DoomState must be a trivially copyable type"); +static_assert(std::is_trivially_copyable::value, + "DoomState must be a trivially copyable type"); struct ControllerContext { @@ -31,6 +39,7 @@ struct ControllerContext SDL_Window *window; SDL_Renderer *renderer; std::vector dooms; + doomid_t nextDoomid = 0; bool quit = false; ExampleAppLog appLog; int columns = 4; @@ -43,13 +52,32 @@ struct ControllerActions void spawn_doom(ControllerContext &ctx) { - size_t nextId = ctx.dooms.size(); + DoomState ds = {}; + ds.id = ctx.nextDoomid; + std::array idBuf; + const char *const argv[] = + { + "doomsim", + "-doomid", + aprintf(idBuf, "%zu", ds.id), + nullptr + }; + + // Close stdin and stdout? Leave them open for now to see the logging + // output. + if (auto err = posix_spawn(&ds.pid, "doomsim", nullptr, nullptr, + const_cast(argv), nullptr)) + { + log_error("Could not spawn doom: %s", strerror(err)); + return; + } - DoomState ds; - ds.alive = true; ctx.dooms.emplace_back(ds); + ++ctx.nextDoomid; + + log_info("Spawned doom#%zu, pid=%d", ds.id, ds.pid); } void perform_actions(ControllerContext &ctx, const ControllerActions &actions) @@ -62,6 +90,53 @@ void perform_actions(ControllerContext &ctx, const ControllerActions &actions) } } +void check_on_dooms(ControllerContext &ctx) +{ + pid_t pid = 0; + + do + { + int wstatus = 0; + + if (pid = waitpid(0, &wstatus, WNOHANG); pid > 0) + { + auto dit = find_in_container(ctx.dooms, [pid] (const auto &ds) { return ds.pid == pid; }); + assert(dit != std::end(ctx.dooms)); + if (dit != std::end(ctx.dooms)) + { + if (WIFEXITED(wstatus)) + log_info("doom#%zu, pid=%d exited with status %d", dit->id, pid, WEXITSTATUS(wstatus)); + else if (WIFSIGNALED(wstatus)) + log_warn("doom#%zu, pid=%d got killed by signal %d", dit->id, pid, WTERMSIG(wstatus)); + + ctx.dooms.erase(dit); + } + } + } while (pid > 0); +} + +void do_networking(ControllerContext &ctx) +{ + // Publish { DP_MT_DoomReady, doomid }. + { + nng_msg *msg = nullptr; + int res = 0; + + if ((res = nng_msg_alloc(&msg, sizeof(dmt_t)))) + dp_nng_fatal("ctrl/alloc", res); + + if ((res = nng_msg_append_u16(msg, DP_MT_DoomReady))) + dp_nng_fatal("ctrl/msg", res); + + if ((res = nng_sendmsg(ctx.pub, msg, 0))) + dp_nng_fatal("ctrl/sendmsg", res); + } +} + +void do_cleanup(ControllerContext &ctx) +{ +} + ControllerActions run_ui(ControllerContext &ctx) { #ifndef IMGUI_DISABLE_DEBUG_TOOLS @@ -179,6 +254,8 @@ int doom_controller_loop(ControllerContext &ctx) } perform_actions(ctx, actions); + check_on_dooms(ctx); + do_networking(ctx); // Start the Dear ImGui frame ImGui_ImplSDLRenderer_NewFrame(); @@ -186,6 +263,7 @@ int doom_controller_loop(ControllerContext &ctx) ImGui::NewFrame(); actions = run_ui(ctx); + // TODO render dooms // Rendering ImGui::Render(); @@ -196,6 +274,8 @@ int doom_controller_loop(ControllerContext &ctx) SDL_RenderPresent(ctx.renderer); } + do_cleanup(ctx); + return 0; } @@ -244,26 +324,18 @@ int main(int argc, char *argv[]) dp_nng_init_limits(1, 1, 1); - auto pubSock = make_ctrl_pub(CtrlUrl); - auto subSock = make_ctrl_sub(DoomUrl); - - ControllerContext ctx = - { - pubSock, - subSock, - window, - renderer, - {}, - {}, - {}, - }; + ControllerContext ctx; + ctx.pub = make_ctrl_pub(CtrlUrl); + ctx.sub = make_ctrl_sub(DoomUrl); + ctx.window = window; + ctx.renderer = renderer; log_add_callback(log_to_imgui, &ctx, LOG_TRACE); int ret = doom_controller_loop(ctx); - nng_close(pubSock); - nng_close(subSock); + nng_close(ctx.pub); + nng_close(ctx.sub); return ret; } \ No newline at end of file diff --git a/src/doomsim.cc b/src/doomsim.cc index d38335d..c5695f9 100644 --- a/src/doomsim.cc +++ b/src/doomsim.cc @@ -22,6 +22,9 @@ typedef struct DoomContext DoomStateFunc *f; } DoomContext; +DEF_DOOM_STATE_FUNC(do_doom_ready); +DEF_DOOM_STATE_FUNC(do_doom_running); + DEF_DOOM_STATE_FUNC(do_doom_ready) { assert(ctx->state == DP_DS_Ready); @@ -72,7 +75,10 @@ DEF_DOOM_STATE_FUNC(do_doom_ready) nng_msg_free(msg); if (mt == DP_MT_RunDoom) + { ctx->state = DP_DS_Running; + ctx->f = do_doom_running; + } else if (mt == DP_MT_QuitDoom) ctx->state = DP_DS_Quit; } diff --git a/src/dp_common.h b/src/dp_common.h index 91c40b0..2542bcb 100644 --- a/src/dp_common.h +++ b/src/dp_common.h @@ -39,6 +39,7 @@ typedef enum DP_MessageType typedef enum DP_DoomState { + DP_DS_Unknown, DP_DS_Ready, DP_DS_Running, DP_DS_Quit, diff --git a/src/dp_util.hpp b/src/dp_util.hpp index 53f2eac..7d49bf1 100644 --- a/src/dp_util.hpp +++ b/src/dp_util.hpp @@ -31,13 +31,14 @@ template return buf.data(); } +template +typename C::iterator find_in_container(C &c, Pred pred) +{ + return std::find_if(std::begin(c), std::end(c), pred); +} + // Copied from the ImGui demo code. Added the AddLog() overload taking a // va_list. - -// Usage: -// static ExampleAppLog my_log; -// my_log.AddLog("Hello %d world\n", 123); -// my_log.Draw("title"); struct ExampleAppLog { ImGuiTextBuffer Buf;