r4549 - developers/zecke/app_restarter

zecke at docs.openmoko.org zecke at docs.openmoko.org
Tue Jul 22 21:30:17 CEST 2008


Author: zecke
Date: 2008-07-22 21:30:16 +0200 (Tue, 22 Jul 2008)
New Revision: 4549

Added:
   developers/zecke/app_restarter/GNUmakefile
Modified:
   developers/zecke/app_restarter/app_restarter.c
Log:
app_restarter: Use some e_alert.c code to provide a X11 interface to ask the user
    Ask the user if an application should be restarted or not


Added: developers/zecke/app_restarter/GNUmakefile
===================================================================
--- developers/zecke/app_restarter/GNUmakefile	                        (rev 0)
+++ developers/zecke/app_restarter/GNUmakefile	2008-07-22 19:30:16 UTC (rev 4549)
@@ -0,0 +1,2 @@
+app_restarter: app_restarter.o
+	$(CC) -o app_restarter app_restarter.o `pkg-config --libs x11`

Modified: developers/zecke/app_restarter/app_restarter.c
===================================================================
--- developers/zecke/app_restarter/app_restarter.c	2008-07-22 14:29:36 UTC (rev 4548)
+++ developers/zecke/app_restarter/app_restarter.c	2008-07-22 19:30:16 UTC (rev 4549)
@@ -14,15 +14,190 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 
+#include <X11/Xlib.h>
+#include <X11/X.h>
+
 static void usage(char* name)
 {
     fprintf(stderr, "%s crash_comment appname [params for app]\n", name);
 }
 
-void fork_and_exec(char* file, int argc, char** argv)
+/*
+ * handle a crash. Open a display connection... create windows...
+ * ...
+ */
+static void handle_crash(int status, const char* question)
 {
+    Display* display;
+    Font font;
+    XFontStruct *fs = NULL;
+    GC gc = 0;
+    Window  win = 0, b1 = 0, b2 = 0;
+    char *title, *button1, *button2;
+    int wid, hih, mask, fw, fh, mh, button;
+    int ww = 320, hh = 240;
+    char line[1024];
+    int w, i, j, k;
+    XSetWindowAttributes att;
+    XGCValues gcv;
+    XEvent ev;
+    KeyCode              key;
+
+    /* create the user interface */
+    display = XOpenDisplay(NULL);
+    if (!display) {
+        fprintf(stderr, "Opening the X display failed\n");
+        exit(-1);
+    }
+
+    font = XLoadFont(display, "fixed");
+    fs = XQueryFont(display, font);
+    if (!fs) {
+        fprintf(stderr, "XQueryFont failed\n");
+        exit(-1);
+    }
+
+    title = "Application Error";
+    button1 = "(F1) Restart";
+    button2 = "(F2) Exit";
+
+    wid = DisplayWidth(display, DefaultScreen(display));
+    hih = DisplayHeight(display, DefaultScreen(display));
+    
+
+    att.background_pixel = WhitePixel(display, DefaultScreen(display));
+    att.border_pixel     = BlackPixel(display, DefaultScreen(display));
+    att.override_redirect = True;
+    mask = CWBackPixel | CWBorderPixel | CWOverrideRedirect;
+
+    win = XCreateWindow(display, DefaultRootWindow(display), 
+                        (wid - ww) / 2, (hih - hh) / 2, ww, hh, 0,
+                        CopyFromParent, InputOutput,
+                        CopyFromParent, mask, &att);
+
+    b1 = XCreateWindow(display, win, -100, -100, 1, 1, 0, CopyFromParent,
+                       InputOutput, CopyFromParent, mask, &att);
+    b2 = XCreateWindow(display, win, -100, -100, 1, 1, 0, CopyFromParent,
+                       InputOutput, CopyFromParent, mask, &att);
+    XMapWindow(display, b1);
+    XMapWindow(display, b2);
+
+    gc = XCreateGC(display, win, 0, &gcv);
+    XSetForeground(display, gc, att.border_pixel);
+    XSelectInput(display, win, KeyPressMask | KeyReleaseMask | ExposureMask);
+
+    /* place the dialog */
+    XMapWindow(display, win);
+
+
+    /* handle the events */
+    fh = fs->ascent + fs->descent;
+    mh = ((ww - 20) / 2) - 20;
+
+    /* fixed size... */
+    w = 20;
+    XMoveResizeWindow(display, b1, w, hh - 15 - fh, mh + 10, fh + 10);
+    XSelectInput(display, b1, ButtonPressMask | ButtonReleaseMask | ExposureMask);
+    w = ww - 20 - mh;
+    XMoveResizeWindow(display, b2, w, hh - 15 - fh, mh + 10, fh + 10);
+    XSelectInput(display, b2, ButtonPressMask | ButtonReleaseMask | ExposureMask);
+
+    XMapWindow(display, win);
+    XGrabPointer(display, win, True, ButtonPressMask | ButtonReleaseMask,
+            GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+    XGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
+    XSetInputFocus(display, win, RevertToPointerRoot, CurrentTime);
+    XSync(display, False);
+
+    button = 0;
+    for (; button == 0;) {
+        XNextEvent(display, &ev);
+        switch (ev.type) {
+        case KeyPress:
+            key = XKeysymToKeycode(display, XStringToKeysym("F1"));
+            if (key == ev.xkey.keycode) {
+                button = 1;
+                break;
+            }
+            key = XKeysymToKeycode(display, XStringToKeysym("F2"));
+            if (key == ev.xkey.keycode) {
+                button = 2;
+                break;
+            }
+            break;
+        case ButtonPress:
+            if (ev.xbutton.window == b1)
+                button = 1;
+            else if (ev.xbutton.window == b2)
+                button = 2;
+            break;
+        case Expose:
+            while (XCheckTypedWindowEvent(display, ev.xexpose.window, Expose, &ev));
+
+            /* outline */
+            XDrawRectangle(display, win, gc, 0, 0, ww - 1, hh - 1);
+
+            XDrawRectangle(display, win, gc, 2, 2, ww - 4 - 1, fh + 4 - 1);
+
+            fw = XTextWidth(fs, title, strlen(title));
+            XDrawString(display, win, gc, 2 + 2 + ((ww - 4 - 4 - fw) / 2) , 2 + 2 + fs->ascent, title, strlen(title));
+
+            i = 0;
+            j = 0;
+            k = 2 + fh + 4 + 2;
+            while (question[i]) {
+                line[j++] = question[i++];
+                if (line[j - 1] == '\n') {
+                    line[j - 1] = 0;
+                    j = 0;
+                    XDrawString(display, win, gc, 4, k + fs->ascent, line, strlen(line));
+                    k += fh + 2;
+                }
+            }
+            fw = XTextWidth(fs, button2, strlen(button1));
+            XDrawRectangle(display, b1, gc, 0, 0, mh - 1, fh + 10 - 1);
+            XDrawString(display, b1, gc, 5 + ((mh - fw) / 2), 5 + fs->ascent, button1, strlen(button1));
+
+            fw = XTextWidth(fs, button2, strlen(button2));
+            XDrawRectangle(display, b2, gc, 0, 0, mh - 1, fh + 10 - 1);
+            XDrawString(display, b2, gc, 5 + ((mh - fw) / 2), 5 + fs->ascent, button2, strlen(button2));
+
+            XSync(display, False);
+            break;
+
+        default:
+            break;
+        }
+    }
+
+
+    /* destruct the X connection and give up the resources */
+    XDestroyWindow(display, win);
+    XFreeGC(display, gc);
+    XFreeFont(display, fs);
+    XSync(display, False);
+    XCloseDisplay(display);
+
+    switch (button) {
+    case 2:
+        fprintf(stderr, "Was asked to quit. Bye Bye\n");
+        exit(-11);
+    case 1:
+    default:
+        break;
+    }
+}
+
+
+/*
+ * Fork and execute the command, wait for the command to finish.
+ * On any kind of exit ask the user to restart
+ */
+int fork_and_exec(char* file, int argc, char** argv)
+{
     pid_t pid = vfork();
 
     if (pid == 0) {
@@ -36,7 +211,10 @@
         while (waitpid(pid, &status, 0) != pid);
 
         fprintf(stderr, "The process exited: %d normal: %d\n", status, WIFEXITED(status));
+        return status;
     }
+
+    assert(0);
 }
 
 int main(int argc, char** argv)
@@ -48,6 +226,11 @@
         return EXIT_FAILURE;
     }
 
+    if (strlen(argv[1]) >= 1024) {
+        fprintf(stderr, "The comment string has to be less than 1024 bytes\n");
+        return EXIT_FAILURE;
+    }
+
     /* Create a list for execvp with a sentinel */
     int commands = argc-3;
     char** command_arguments = (char**) malloc(sizeof(char*)*(commands+1));
@@ -55,6 +238,8 @@
         command_arguments[i] = argv[2+i];
     command_arguments[commands] = NULL;
 
-    for (;;)
-        fork_and_exec(argv[2], commands, command_arguments);
+    for (;;) {
+        int status = fork_and_exec(argv[2], commands, command_arguments);
+        handle_crash(status, argv[1]);
+    }
 }





More information about the commitlog mailing list