#include <syslog.h>
#include <sys/wait.h>
#endif
-#include "qapi/qmp/json-streamer.h"
#include "qapi/qmp/json-parser.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qjson.h"
return f;
}
-#ifndef _WIN32
-static bool ga_open_pidfile(const char *pidfile)
-{
- int pidfd;
- char pidstr[32];
-
- pidfd = qemu_open(pidfile, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
- if (pidfd == -1 || lockf(pidfd, F_TLOCK, 0)) {
- g_critical("Cannot lock pid file, %s", strerror(errno));
- if (pidfd != -1) {
- close(pidfd);
- }
- return false;
- }
-
- if (ftruncate(pidfd, 0)) {
- g_critical("Failed to truncate pid file");
- goto fail;
- }
- snprintf(pidstr, sizeof(pidstr), "%d\n", getpid());
- if (write(pidfd, pidstr, strlen(pidstr)) != strlen(pidstr)) {
- g_critical("Failed to write pid file");
- goto fail;
- }
-
- /* keep pidfile open & locked forever */
- return true;
-
-fail:
- unlink(pidfile);
- close(pidfd);
- return false;
-}
-#else /* _WIN32 */
-static bool ga_open_pidfile(const char *pidfile)
-{
- return true;
-}
-#endif
-
static gint ga_strcmp(gconstpointer str1, gconstpointer str2)
{
return strcmp(str1, str2);
ga_enable_logging(s);
g_warning("logging re-enabled due to filesystem unfreeze");
if (s->deferred_options.pid_filepath) {
- if (!ga_open_pidfile(s->deferred_options.pid_filepath)) {
- g_warning("failed to create/open pid file");
+ Error *err = NULL;
+
+ if (!qemu_write_pidfile(s->deferred_options.pid_filepath, &err)) {
+ g_warning("%s", error_get_pretty(err));
+ error_free(err);
}
s->deferred_options.pid_filepath = NULL;
}
}
if (pidfile) {
- if (!ga_open_pidfile(pidfile)) {
- g_critical("failed to create pidfile");
+ Error *err = NULL;
+
+ if (!qemu_write_pidfile(pidfile, &err)) {
+ g_critical("%s", error_get_pretty(err));
+ error_free(err);
exit(EXIT_FAILURE);
}
}
}
/* handle requests/control events coming in over the channel */
-static void process_event(JSONMessageParser *parser, GQueue *tokens)
+static void process_event(void *opaque, QObject *obj, Error *err)
{
- GAState *s = container_of(parser, GAState, parser);
- QDict *qdict;
- Error *err = NULL;
+ GAState *s = opaque;
+ QDict *req, *rsp;
int ret;
- g_assert(s && parser);
-
g_debug("process_event: called");
- qdict = qobject_to(QDict, json_parser_parse_err(tokens, NULL, &err));
- if (err || !qdict) {
- qobject_unref(qdict);
- if (!err) {
- g_warning("failed to parse event: unknown error");
- error_setg(&err, QERR_JSON_PARSING);
- } else {
- g_warning("failed to parse event: %s", error_get_pretty(err));
- }
- qdict = qmp_error_response(err);
+ assert(!obj != !err);
+ if (err) {
+ goto err;
}
-
- /* handle host->guest commands */
- if (qdict_haskey(qdict, "execute")) {
- process_command(s, qdict);
- } else {
- if (!qdict_haskey(qdict, "error")) {
- qobject_unref(qdict);
- g_warning("unrecognized payload format");
- error_setg(&err, QERR_UNSUPPORTED);
- qdict = qmp_error_response(err);
- }
- ret = send_response(s, qdict);
- if (ret < 0) {
- g_warning("error sending error response: %s", strerror(-ret));
- }
+ req = qobject_to(QDict, obj);
+ if (!req) {
+ error_setg(&err, "Input must be a JSON object");
+ goto err;
+ }
+ if (!qdict_haskey(req, "execute")) {
+ g_warning("unrecognized payload format");
+ error_setg(&err, QERR_UNSUPPORTED);
+ goto err;
}
- qobject_unref(qdict);
+ process_command(s, req);
+ qobject_unref(obj);
+ return;
+
+err:
+ g_warning("failed to parse event: %s", error_get_pretty(err));
+ rsp = qmp_error_response(err);
+ ret = send_response(s, rsp);
+ if (ret < 0) {
+ g_warning("error sending error response: %s", strerror(-ret));
+ }
+ qobject_unref(rsp);
+ qobject_unref(obj);
}
/* false return signals GAChannel to close the current client connection */
s->command_state = ga_command_state_new();
ga_command_state_init(s, s->command_state);
ga_command_state_init_all(s->command_state);
- json_message_parser_init(&s->parser, process_event);
+ json_message_parser_init(&s->parser, process_event, s, NULL);
#ifndef _WIN32
if (!register_signal_handlers()) {