posix_spawn() doomsims
The doomsim startup routine or the controller startup publish are broken. The doomsims never transition from DP_DS_Ready state.
This commit is contained in:
parent
c41066ebeb
commit
823932af16
4 changed files with 105 additions and 25 deletions
|
@ -4,10 +4,15 @@
|
||||||
#include <backends/imgui_impl_sdlrenderer.h>
|
#include <backends/imgui_impl_sdlrenderer.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cerrno>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <spawn.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include "dp_common.h"
|
#include "dp_common.h"
|
||||||
#include "dp_util.hpp"
|
#include "dp_util.hpp"
|
||||||
|
|
||||||
|
@ -19,10 +24,13 @@ void dp_sdl_fatal(const char *const msg)
|
||||||
|
|
||||||
struct DoomState
|
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<DoomState>::value, "DoomState must be a trivially copyable type");
|
static_assert(std::is_trivially_copyable<DoomState>::value,
|
||||||
|
"DoomState must be a trivially copyable type");
|
||||||
|
|
||||||
struct ControllerContext
|
struct ControllerContext
|
||||||
{
|
{
|
||||||
|
@ -31,6 +39,7 @@ struct ControllerContext
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
SDL_Renderer *renderer;
|
SDL_Renderer *renderer;
|
||||||
std::vector<DoomState> dooms;
|
std::vector<DoomState> dooms;
|
||||||
|
doomid_t nextDoomid = 0;
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
ExampleAppLog appLog;
|
ExampleAppLog appLog;
|
||||||
int columns = 4;
|
int columns = 4;
|
||||||
|
@ -43,13 +52,32 @@ struct ControllerActions
|
||||||
|
|
||||||
void spawn_doom(ControllerContext &ctx)
|
void spawn_doom(ControllerContext &ctx)
|
||||||
{
|
{
|
||||||
size_t nextId = ctx.dooms.size();
|
DoomState ds = {};
|
||||||
|
ds.id = ctx.nextDoomid;
|
||||||
|
|
||||||
|
std::array<char, 32> 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<char *const *>(argv), nullptr))
|
||||||
|
{
|
||||||
|
log_error("Could not spawn doom: %s", strerror(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DoomState ds;
|
|
||||||
ds.alive = true;
|
|
||||||
ctx.dooms.emplace_back(ds);
|
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)
|
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)
|
ControllerActions run_ui(ControllerContext &ctx)
|
||||||
{
|
{
|
||||||
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
||||||
|
@ -179,6 +254,8 @@ int doom_controller_loop(ControllerContext &ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
perform_actions(ctx, actions);
|
perform_actions(ctx, actions);
|
||||||
|
check_on_dooms(ctx);
|
||||||
|
do_networking(ctx);
|
||||||
|
|
||||||
// Start the Dear ImGui frame
|
// Start the Dear ImGui frame
|
||||||
ImGui_ImplSDLRenderer_NewFrame();
|
ImGui_ImplSDLRenderer_NewFrame();
|
||||||
|
@ -186,6 +263,7 @@ int doom_controller_loop(ControllerContext &ctx)
|
||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
|
|
||||||
actions = run_ui(ctx);
|
actions = run_ui(ctx);
|
||||||
|
// TODO render dooms
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
|
@ -196,6 +274,8 @@ int doom_controller_loop(ControllerContext &ctx)
|
||||||
SDL_RenderPresent(ctx.renderer);
|
SDL_RenderPresent(ctx.renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do_cleanup(ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,26 +324,18 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
dp_nng_init_limits(1, 1, 1);
|
dp_nng_init_limits(1, 1, 1);
|
||||||
|
|
||||||
auto pubSock = make_ctrl_pub(CtrlUrl);
|
ControllerContext ctx;
|
||||||
auto subSock = make_ctrl_sub(DoomUrl);
|
ctx.pub = make_ctrl_pub(CtrlUrl);
|
||||||
|
ctx.sub = make_ctrl_sub(DoomUrl);
|
||||||
ControllerContext ctx =
|
ctx.window = window;
|
||||||
{
|
ctx.renderer = renderer;
|
||||||
pubSock,
|
|
||||||
subSock,
|
|
||||||
window,
|
|
||||||
renderer,
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
|
|
||||||
log_add_callback(log_to_imgui, &ctx, LOG_TRACE);
|
log_add_callback(log_to_imgui, &ctx, LOG_TRACE);
|
||||||
|
|
||||||
int ret = doom_controller_loop(ctx);
|
int ret = doom_controller_loop(ctx);
|
||||||
|
|
||||||
nng_close(pubSock);
|
nng_close(ctx.pub);
|
||||||
nng_close(subSock);
|
nng_close(ctx.sub);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
|
@ -22,6 +22,9 @@ typedef struct DoomContext
|
||||||
DoomStateFunc *f;
|
DoomStateFunc *f;
|
||||||
} DoomContext;
|
} DoomContext;
|
||||||
|
|
||||||
|
DEF_DOOM_STATE_FUNC(do_doom_ready);
|
||||||
|
DEF_DOOM_STATE_FUNC(do_doom_running);
|
||||||
|
|
||||||
DEF_DOOM_STATE_FUNC(do_doom_ready)
|
DEF_DOOM_STATE_FUNC(do_doom_ready)
|
||||||
{
|
{
|
||||||
assert(ctx->state == DP_DS_Ready);
|
assert(ctx->state == DP_DS_Ready);
|
||||||
|
@ -72,7 +75,10 @@ DEF_DOOM_STATE_FUNC(do_doom_ready)
|
||||||
nng_msg_free(msg);
|
nng_msg_free(msg);
|
||||||
|
|
||||||
if (mt == DP_MT_RunDoom)
|
if (mt == DP_MT_RunDoom)
|
||||||
|
{
|
||||||
ctx->state = DP_DS_Running;
|
ctx->state = DP_DS_Running;
|
||||||
|
ctx->f = do_doom_running;
|
||||||
|
}
|
||||||
else if (mt == DP_MT_QuitDoom)
|
else if (mt == DP_MT_QuitDoom)
|
||||||
ctx->state = DP_DS_Quit;
|
ctx->state = DP_DS_Quit;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ typedef enum DP_MessageType
|
||||||
|
|
||||||
typedef enum DP_DoomState
|
typedef enum DP_DoomState
|
||||||
{
|
{
|
||||||
|
DP_DS_Unknown,
|
||||||
DP_DS_Ready,
|
DP_DS_Ready,
|
||||||
DP_DS_Running,
|
DP_DS_Running,
|
||||||
DP_DS_Quit,
|
DP_DS_Quit,
|
||||||
|
|
|
@ -31,13 +31,14 @@ template<size_t Size>
|
||||||
return buf.data();
|
return buf.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename C, typename Pred>
|
||||||
|
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
|
// Copied from the ImGui demo code. Added the AddLog() overload taking a
|
||||||
// va_list.
|
// va_list.
|
||||||
|
|
||||||
// Usage:
|
|
||||||
// static ExampleAppLog my_log;
|
|
||||||
// my_log.AddLog("Hello %d world\n", 123);
|
|
||||||
// my_log.Draw("title");
|
|
||||||
struct ExampleAppLog
|
struct ExampleAppLog
|
||||||
{
|
{
|
||||||
ImGuiTextBuffer Buf;
|
ImGuiTextBuffer Buf;
|
||||||
|
|
Loading…
Reference in a new issue