pid_t qemu_pid; /* our child QEMU process */
};
+static GHookList abrt_hooks;
static GList *qtest_instances;
static struct sigaction sigact_old;
}
}
+static void kill_qemu_hook_func(void *s)
+{
+ kill_qemu(s);
+}
+
static void sigabrt_handler(int signo)
{
- GList *elem;
- for (elem = qtest_instances; elem; elem = elem->next) {
- kill_qemu(elem->data);
- }
+ g_hook_list_invoke(&abrt_hooks, FALSE);
}
static void setup_sigabrt_handler(void)
sigaction(SIGABRT, &sigact_old, NULL);
}
+void qtest_add_abrt_handler(GHookFunc fn, const void *data)
+{
+ GHook *hook;
+
+ /* Only install SIGABRT handler once */
+ if (!abrt_hooks.is_setup) {
+ g_hook_list_init(&abrt_hooks, sizeof(GHook));
+ setup_sigabrt_handler();
+ }
+
+ hook = g_hook_alloc(&abrt_hooks);
+ hook->func = fn;
+ hook->data = (void *)data;
+
+ g_hook_prepend(&abrt_hooks, hook);
+}
+
QTestState *qtest_init(const char *extra_args)
{
QTestState *s;
sock = init_socket(socket_path);
qmpsock = init_socket(qmp_socket_path);
- /* Only install SIGABRT handler once */
- if (!qtest_instances) {
- setup_sigabrt_handler();
- }
-
- qtest_instances = g_list_prepend(qtest_instances, s);
+ qtest_add_abrt_handler(kill_qemu_hook_func, s);
s->qemu_pid = fork();
if (s->qemu_pid == 0) {
void qtest_quit(QTestState *s)
{
+ qtest_instances = g_list_remove(qtest_instances, s);
+ g_hook_destroy_link(&abrt_hooks, g_hook_find_data(&abrt_hooks, TRUE, s));
+
/* Uninstall SIGABRT handler on last instance */
- if (qtest_instances && !qtest_instances->next) {
+ if (!qtest_instances) {
cleanup_sigabrt_handler();
}
- qtest_instances = g_list_remove(qtest_instances, s);
-
kill_qemu(s);
close(s->fd);
close(s->qmp_fd);
QDict *response;
} QMPResponseParser;
-static void qmp_response(JSONMessageParser *parser, QList *tokens)
+static void qmp_response(JSONMessageParser *parser, GQueue *tokens)
{
QMPResponseParser *qmp = container_of(parser, QMPResponseParser, parser);
QObject *obj;
g_strfreev(args);
}
-void qtest_add_func(const char *str, void (*fn))
+void qtest_add_func(const char *str, void (*fn)(void))
{
gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
g_test_add_func(path, fn);
g_free(path);
}
-void qtest_add_data_func(const char *str, const void *data, void (*fn))
+void qtest_add_data_func(const char *str, const void *data,
+ void (*fn)(const void *))
{
gchar *path = g_strdup_printf("/%s/%s", qtest_get_arch(), str);
g_test_add_data_func(path, data, fn);