[aisleriot] Rework scheme exception handling
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [aisleriot] Rework scheme exception handling
- Date: Thu, 14 Apr 2011 13:19:32 +0000 (UTC)
commit 3d1b9a2bdc3c302cbeb26cd799a278efe56885d3
Author: Christian Persch <chpe gnome org>
Date: Thu Apr 14 15:12:52 2011 +0200
Rework scheme exception handling
src/game.c | 92 ++++++++++++++++++++++++---------------------------------
src/game.h | 7 ++--
src/window.c | 57 ++++++++++++++++++++++++------------
3 files changed, 81 insertions(+), 75 deletions(-)
---
diff --git a/src/game.c b/src/game.c
index 4156f41..58b74b0 100644
--- a/src/game.c
+++ b/src/game.c
@@ -1,6 +1,6 @@
/*
* Copyright © 1998, 2003 Jonathan Blandford <jrb alum mit edu>
- * Copyright © 2007 Christian Persch
+ * Copyright © 2007, 2011 Christian Persch
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -44,6 +44,11 @@
#define I_(string) g_intern_static_string (string)
+struct _AisleriotGameClass
+{
+ GObjectClass parent_class;
+};
+
struct _AisleriotGame
{
GObject parent_instance;
@@ -278,8 +283,6 @@ typedef struct {
SCM lambda;
SCM *args;
gsize n_args;
- SCM retval;
- gboolean exception;
} CallData;
static char *
@@ -396,50 +399,19 @@ game_scm_pre_unwind_handler (void *user_data,
SCM tag,
SCM throw_args)
{
- CallData *data = (CallData *) user_data;
- AisleriotGame *game = app_game;
- char *message = NULL;
- int error_fd;
- char *error_file = NULL;
- GError *error = NULL;
-
- if (data)
- data->exception = TRUE;
+ GError **error = user_data;
+ char *message;
- g_print ("preunwind handler\n");
-
- if (game->had_exception)
- goto out;
+ /* Not interested in errors, or already had an exception */
+ if (error == NULL || *error != NULL)
+ return SCM_UNDEFINED;
message = cscmi_exception_get_backtrace (tag, throw_args);
- if (!message) {
- g_warning ("A scheme exception occurred, but there was no exception info\n");
- goto out;
- }
-
- g_print ("scheme exception: \n\n%s\n\n", message);
- goto out;
-
- error_fd = g_file_open_tmp ("arcrashXXXXXX", &error_file, &error);
- if (error_fd >= 0) {
- close (error_fd);
- g_file_set_contents (error_file, message, strlen (message), NULL);
-
- /* Tell the frontend about the problem */
- g_signal_emit (game, signals[EXCEPTION], 0, error_file);
- g_free (error_file);
- } else {
- g_warning ("A scheme exception occurred, and aisleriot could not create a temporary file to report it: %s",
- error->message);
- g_error_free (error);
- }
-
-out:
- /* This game is over, but don't count it in the statistics */
- set_game_state (game, GAME_LOADED);
-
- g_free (message);
-
+ g_set_error (error,
+ AISLERIOT_GAME_ERROR,
+ GAME_ERROR_EXCEPTION,
+ message ? message
+ : "A scheme exception occurred, but there was no exception info");
return SCM_UNDEFINED;
}
@@ -481,15 +453,23 @@ game_scm_call (SCM lambda,
gsize n_args,
SCM *retval)
{
- CallData data = { lambda, args, n_args, FALSE };
+ CallData data = { lambda, args, n_args };
+ GError *error = NULL;
SCM rv;
rv = scm_c_catch (SCM_BOOL_T,
game_scm_call_lambda, &data,
- game_scm_catch_handler, &data,
- game_scm_pre_unwind_handler, &data);
- if (data.exception)
+ game_scm_catch_handler, NULL,
+ game_scm_pre_unwind_handler, &error);
+ if (error) {
+ g_signal_emit (app_game, signals[EXCEPTION], 0, error);
+ g_error_free (error);
+
+ /* This game is over, but don't count it in the statistics */
+ set_game_state (app_game, GAME_LOADED);
+
return FALSE;
+ }
if (retval)
*retval = rv;
@@ -1248,6 +1228,7 @@ aisleriot_game_class_init (AisleriotGameClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GType param_types[] = { G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE };
+ GType error_types[] = { G_TYPE_ERROR | G_SIGNAL_TYPE_STATIC_SCOPE };
GType ptr_types[] = { G_TYPE_POINTER };
gobject_class->constructor = aisleriot_game_constructor;
@@ -1310,9 +1291,9 @@ aisleriot_game_class_init (AisleriotGameClass *klass)
(GSignalFlags) (G_SIGNAL_RUN_LAST),
NULL,
NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
+ g_cclosure_marshal_VOID__BOXED,
G_TYPE_NONE,
- 1, param_types);
+ 1, error_types);
g_object_class_install_property
(gobject_class,
@@ -2418,12 +2399,17 @@ aisleriot_game_set_click_to_move (AisleriotGame *game,
void
aisleriot_game_generate_exception (AisleriotGame *game)
{
- CallData data = { SCM_EOL, NULL, 0, FALSE };
+ GError *error = NULL;
scm_c_catch (SCM_BOOL_T,
(scm_t_catch_body) scm_c_eval_string, (void *) "(/ 1 0)",
- game_scm_catch_handler, &data,
- game_scm_pre_unwind_handler, &data);
+ game_scm_catch_handler, NULL,
+ game_scm_pre_unwind_handler, &error);
+
+ if (error) {
+ g_signal_emit (app_game, signals[EXCEPTION], 0, error);
+ g_error_free (error);
+ }
}
/**
diff --git a/src/game.h b/src/game.h
index 6d4a0a1..551cbc4 100644
--- a/src/game.h
+++ b/src/game.h
@@ -111,11 +111,12 @@ char *ar_slot_get_hint_string (ArSlot *slot,
#define AISLERIOT_GAME_OPTIONS_MAX (0x7FFFFFFF) /* 31 bits, since we're using int not guint */
typedef struct _AisleriotGame AisleriotGame;
-typedef GObjectClass AisleriotGameClass;
+typedef struct _AisleriotGameClass AisleriotGameClass;
enum {
- GAME_ERROR_GENERIC = 0,
- GAME_ERROR_FALLBACK = 1
+ GAME_ERROR_EXCEPTION = 0,
+ GAME_ERROR_GENERIC = 1,
+ GAME_ERROR_FALLBACK = 2
};
typedef enum {
diff --git a/src/window.c b/src/window.c
index a240d81..ca5b046 100644
--- a/src/window.c
+++ b/src/window.c
@@ -92,7 +92,7 @@ enum
ACTION_LEAVE_FULLSCREEN,
LAST_ACTION
};
-
+
struct _AisleriotWindowPrivate
{
AisleriotGame *game;
@@ -1677,14 +1677,18 @@ game_exception_response_cb (GtkWidget *dialog,
AisleriotWindow *window)
{
AisleriotWindowPrivate *priv = window->priv;
- const char *error_file;
+ GError *error;
+ gboolean did_report;
- error_file = g_object_get_data (G_OBJECT (dialog), "error-file");
- g_assert (error_file != NULL);
+ error = g_object_get_data (G_OBJECT (dialog), "error");
+ g_assert (error != NULL);
+ did_report = FALSE;
if (response == GTK_RESPONSE_ACCEPT) {
GError *err = NULL;
char pidstr[64];
+ int fd;
+ char *error_file;
const char * const argv[] = {
"bug-buddy",
"--package", "gnome-games",
@@ -1698,20 +1702,34 @@ game_exception_response_cb (GtkWidget *dialog,
g_snprintf (pidstr, sizeof (pidstr), "%d", getpid ());
- if (!g_spawn_async (
- NULL /* working dir */,
- (char **) argv,
- NULL /* envp */,
- G_SPAWN_SEARCH_PATH,
- NULL, NULL,
- NULL,
- &err)) {
- g_warning ("Failed to launch bug buddy: %s\n", err->message);
+ fd = g_file_open_tmp ("arcrashXXXXXX", &error_file, &err);
+ if (fd >= 0) {
+ close (fd);
+
+ g_file_set_contents (error_file, error->message, strlen (error->message), NULL);
+
+ if (g_spawn_async (NULL /* working dir */,
+ (char **) argv,
+ NULL /* envp */,
+ G_SPAWN_SEARCH_PATH,
+ NULL, NULL,
+ NULL,
+ &err)) {
+ did_report = TRUE;
+ } else {
+ g_warning ("Failed to launch bug buddy: %s\n", err->message);
+ g_error_free (err);
+ }
+
+ g_free (error_file);
+ } else {
+ g_warning ("Failed to create temp file: %s\n", err->message);
g_error_free (err);
}
+ }
- /* FIXMEchpe: can't unlink now since bug buddy still needs it... what to do? */
- /* unlink (error_file); */
+ if (!did_report) {
+ g_printerr ("Aisleriot " VERSION " scheme exception occurred\n-- 8< --\n%s\n-- >8 --\n", error->message);
}
gtk_widget_destroy (dialog);
@@ -1724,12 +1742,12 @@ game_exception_response_cb (GtkWidget *dialog,
static void
game_exception_cb (AisleriotGame *game,
- const char *error_file,
+ const GError *error,
AisleriotWindow *window)
{
GtkWidget *dialog;
- g_return_if_fail (error_file != NULL);
+ g_return_if_fail (error != NULL);
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -1755,8 +1773,9 @@ game_exception_cb (AisleriotGame *game,
g_signal_connect (dialog, "response",
G_CALLBACK (game_exception_response_cb), window);
- g_object_set_data_full (G_OBJECT (dialog), "error-file",
- g_strdup (error_file), g_free);
+ g_object_set_data_full (G_OBJECT (dialog), "error",
+ g_error_copy (error),
+ (GDestroyNotify) g_error_free);
gtk_widget_show (dialog);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]