static void g_scanner_msg_handler (GScanner *scanner, gchar *message, gboolean is_error) { g_return_if_fail (scanner != NULL); _g_fprintf (stderr, "%s:%d: ", scanner->input_name ? scanner->input_name : "<memory>", scanner->line); if (is_error) _g_fprintf (stderr, "error: "); _g_fprintf (stderr, "%s\n", message); }
static gchar* strdup_convert (const gchar *string, const gchar *charset) { if (!g_utf8_validate (string, -1, NULL)) { GString *gstring = g_string_new ("[Invalid UTF-8] "); guchar *p; for (p = (guchar *)string; *p; p++) { if (CHAR_IS_SAFE(*p) && !(*p == '\r' && *(p + 1) != '\n') && *p < 0x80) g_string_append_c (gstring, *p); else g_string_append_printf (gstring, "\\x%02x", (guint)(guchar)*p); } return g_string_free (gstring, FALSE); } else { GError *err = NULL; gchar *result = g_convert_with_fallback (string, -1, charset, "UTF-8", "?", NULL, NULL, &err); if (result) return result; else { #ifdef USE_LIBICONV_GNU /* No libiconv in Android, so we only duplicate message if no * USE_LIBICONV_GNU */ /* Not thread-safe, but doesn't matter if we print the warning twice */ static gboolean warned = FALSE; if (!warned) { warned = TRUE; _g_fprintf (stderr, "GLib: Cannot convert message: %s\n", err->message); } g_error_free (err); #endif return g_strdup (string); } } }
void g_on_error_query (const gchar *prg_name) { #ifndef G_OS_WIN32 static const gchar *query1 = "[E]xit, [H]alt"; static const gchar *query2 = ", show [S]tack trace"; static const gchar *query3 = " or [P]roceed"; gchar buf[16]; if (!prg_name) prg_name = g_get_prgname (); retry: if (prg_name) _g_fprintf (stdout, "%s (pid:%u): %s%s%s: ", prg_name, (guint) getpid (), query1, query2, query3); else _g_fprintf (stdout, "(process:%u): %s%s: ", (guint) getpid (), query1, query3); fflush (stdout); if (isatty(0) && isatty(1)) fgets (buf, 8, stdin); else strcpy (buf, "E\n"); if ((buf[0] == 'E' || buf[0] == 'e') && buf[1] == '\n') _exit (0); else if ((buf[0] == 'P' || buf[0] == 'p') && buf[1] == '\n') return; else if (prg_name && (buf[0] == 'S' || buf[0] == 's') && buf[1] == '\n') { g_on_error_stack_trace (prg_name); goto retry; } else if ((buf[0] == 'H' || buf[0] == 'h') && buf[1] == '\n') { while (glib_on_error_halt) ; glib_on_error_halt = TRUE; return; } else goto retry; #else if (!prg_name) prg_name = g_get_prgname (); MessageBox (NULL, "g_on_error_query called, program terminating", (prg_name && *prg_name) ? prg_name : NULL, MB_OK|MB_ICONERROR); _exit(0); #endif }
static void stack_trace (char **args) { pid_t pid; int in_fd[2]; int out_fd[2]; SELECT_MASK fdset; SELECT_MASK readset; struct timeval tv; int sel, index, state; char buffer[256]; char c; stack_trace_done = FALSE; signal (SIGCHLD, stack_trace_sigchld); if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1)) { perror ("unable to open pipe"); _exit (0); } pid = fork (); if (pid == 0) { close (0); dup (in_fd[0]); /* set the stdin to the in pipe */ close (1); dup (out_fd[1]); /* set the stdout to the out pipe */ close (2); dup (out_fd[1]); /* set the stderr to the out pipe */ execvp (args[0], args); /* exec gdb */ perror ("exec failed"); _exit (0); } else if (pid == (pid_t) -1) { perror ("unable to fork"); _exit (0); } FD_ZERO (&fdset); FD_SET (out_fd[0], &fdset); write (in_fd[1], "backtrace\n", 10); write (in_fd[1], "p x = 0\n", 8); write (in_fd[1], "quit\n", 5); index = 0; state = 0; while (1) { readset = fdset; tv.tv_sec = 1; tv.tv_usec = 0; sel = select (FD_SETSIZE, &readset, NULL, NULL, &tv); if (sel == -1) break; if ((sel > 0) && (FD_ISSET (out_fd[0], &readset))) { if (read (out_fd[0], &c, 1)) { switch (state) { case 0: if (c == '#') { state = 1; index = 0; buffer[index++] = c; } break; case 1: buffer[index++] = c; if ((c == '\n') || (c == '\r')) { buffer[index] = 0; _g_fprintf (stdout, "%s", buffer); state = 0; index = 0; } break; default: break; } } } else if (stack_trace_done) break; } close (in_fd[0]); close (in_fd[1]); close (out_fd[0]); close (out_fd[1]); _exit (0); }