shared: add exec_command_status_build_json() and ExecCommandStatus varlink type to common

Add exec_command_status_build_json() and exec_command_status_list_build_json() to varlink-common, alongside exec_command_build_json() and exec_command_list_build_json(). The status list function is the runtime counterpart of the command list function — the two arrays are positionally aligned so index N in the status array corresponds to index N in the command array. Commands that have not yet run produce null entries to preserve alignment.

Add the ExecCommandStatus varlink struct type to varlink-idl-common next to ExecCommand. It contains PID, timestamps, and mutually exclusive ExitStatus (int, for normal exit) / ExitSignal (string, for signal kill).
This commit is contained in:
Ivan Kruglov
2026-05-15 00:02:01 -07:00
committed by ikruglov
parent 59203dca3a
commit 5305da009a
4 changed files with 77 additions and 0 deletions
+59
View File
@@ -7,6 +7,8 @@
#include "cpu-set-util.h"
#include "execute.h"
#include "json-util.h"
#include "pidref.h"
#include "process-util.h"
#include "rlimit-util.h"
#include "varlink-common.h"
#include "varlink-unit.h"
@@ -159,3 +161,60 @@ int exec_command_list_build_json(sd_json_variant **ret, const char *name, void *
*ret = TAKE_PTR(v);
return 0;
}
int exec_command_status_build_json(sd_json_variant **ret, const char *name, void *userdata) {
ExecStatus *status = ASSERT_PTR(userdata);
assert(ret);
if (!pid_is_valid(status->pid)) {
*ret = NULL;
return 0;
}
return sd_json_buildo(
ret,
/* TODO: replace with a real PidRef once ExecStatus carries one */
SD_JSON_BUILD_PAIR("PID", JSON_BUILD_PIDREF(&PIDREF_MAKE_FROM_PID(status->pid))),
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("StartTimestamp", &status->start_timestamp),
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("ExitTimestamp", &status->exit_timestamp),
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("HandoffTimestamp", &status->handoff_timestamp),
SD_JSON_BUILD_PAIR_CONDITION(status->code > 0, "Code", SD_JSON_BUILD_INTEGER(status->code)),
SD_JSON_BUILD_PAIR_CONDITION(status->code > 0, "Status", SD_JSON_BUILD_INTEGER(status->status)));
}
/* exec_command_status_list_build_json() is the runtime counterpart of exec_command_list_build_json().
* The two arrays are positionally aligned: index N in the status array corresponds to index N in the
* command array. Commands that have not yet run produce null entries to preserve alignment. */
int exec_command_status_list_build_json(sd_json_variant **ret, const char *name, void *userdata) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
ExecCommand *list = userdata;
bool any_ran = false;
int r;
assert(ret);
LIST_FOREACH(command, c, list) {
_cleanup_(sd_json_variant_unrefp) sd_json_variant *entry = NULL;
r = exec_command_status_build_json(&entry, /* name= */ NULL, &c->exec_status);
if (r < 0)
return r;
if (entry) {
any_ran = true;
r = sd_json_variant_append_array(&v, entry);
} else
r = sd_json_variant_append_arrayb(&v, SD_JSON_BUILD_NULL);
if (r < 0)
return r;
}
if (!any_ran) {
*ret = NULL;
return 0;
}
*ret = TAKE_PTR(v);
return 0;
}
+2
View File
@@ -9,4 +9,6 @@ int cpuset_build_json(sd_json_variant **ret, const char *name, void *userdata);
const char* varlink_error_id_from_bus_error(const sd_bus_error *e);
int exec_command_build_json(sd_json_variant **ret, const char *name, void *userdata);
int exec_command_list_build_json(sd_json_variant **ret, const char *name, void *userdata);
int exec_command_status_build_json(sd_json_variant **ret, const char *name, void *userdata);
int exec_command_status_list_build_json(sd_json_variant **ret, const char *name, void *userdata);
int varlink_reply_bus_error(sd_varlink *link, int r, const sd_bus_error *e);
+15
View File
@@ -71,6 +71,21 @@ SD_VARLINK_DEFINE_STRUCT_TYPE(
SD_VARLINK_FIELD_COMMENT("Run via shell"),
SD_VARLINK_DEFINE_FIELD(viaShell, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_STRUCT_TYPE(
ExecCommandStatus,
SD_VARLINK_FIELD_COMMENT("Process ID"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(PID, ProcessId, 0),
SD_VARLINK_FIELD_COMMENT("Timestamp when the process started"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(StartTimestamp, Timestamp, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Timestamp when the process exited"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(ExitTimestamp, Timestamp, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Timestamp when the process was handed off to the executor"),
SD_VARLINK_DEFINE_FIELD_BY_TYPE(HandoffTimestamp, Timestamp, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Termination reason (si_code): CLD_EXITED, CLD_KILLED, CLD_DUMPED"),
SD_VARLINK_DEFINE_FIELD(Code, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Exit code or signal number (si_status), meaning depends on Code"),
SD_VARLINK_DEFINE_FIELD(Status, SD_VARLINK_INT, SD_VARLINK_NULLABLE));
SD_VARLINK_DEFINE_ENUM_TYPE(
ExecOutputType,
SD_VARLINK_DEFINE_ENUM_VALUE(inherit),
+1
View File
@@ -9,6 +9,7 @@ extern const sd_varlink_symbol vl_type_RateLimit;
extern const sd_varlink_symbol vl_type_ResourceLimit;
extern const sd_varlink_symbol vl_type_ResourceLimitTable;
extern const sd_varlink_symbol vl_type_ExecCommand;
extern const sd_varlink_symbol vl_type_ExecCommandStatus;
extern const sd_varlink_symbol vl_type_ExecOutputType;
extern const sd_varlink_symbol vl_type_CGroupPressureWatch;
extern const sd_varlink_symbol vl_type_ManagedOOMMode;