/* gimpdebug * Copyright (C) 2018 Jehan * * 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 * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * GimpDebug simply displays a dialog with debug data (backtraces, * version, etc.), proposing to create a bug report. The reason why it * is a separate executable is simply that when the program crashed, * even though some actions are possible before exit() by catching fatal * errors and signals, it may not be possible to allocate memory * anymore. Therefore creating a new dialog is an impossible action. * So we call instead a separate program, then exit. */ #include "config.h" #include #include #include #include #include #include #include #ifdef G_OS_WIN32 #include #endif #include #include "app/widgets/gimpcriticaldialog.h" int main (int argc, char **argv) { const gchar *program; const gchar *pid; const gchar *reason; const gchar *message; const gchar *bt_file = NULL; const gchar *last_version = NULL; const gchar *release_date = NULL; gchar *trace = NULL; gchar *error; GtkWidget *dialog; #ifdef G_OS_WIN32 if (AttachConsole (ATTACH_PARENT_PROCESS) != 0 && ! g_getenv ("TERM") && ! g_getenv ("SHELL")) { /* 'r' is needed to prevent interleaving and '+' to support colors */ #ifndef _UCRT freopen ("CONOUT$", "r+", stdout); freopen ("CONOUT$", "r+", stderr); #else FILE* fileOut; FILE* fileErr; errno_t errOut = freopen_s (&fileOut, "CONOUT$", "r+", stdout); errno_t errErr = freopen_s (&fileErr, "CONOUT$", "r+", stderr); if (errOut != 0 || errErr != 0) g_warning ("Failed to redirect streams to CONOUT$. stdout: %d, stderr: %d", errOut, errErr); #endif _flushall (); { /* CTRL+C handling */ HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE); SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT); } } #endif if (argc != 6 && argc != 8) { g_print ("Usage: gimp-debug-tool-%s [PROGRAM] [PID] [REASON] [MESSAGE] [BT_FILE] " "([LAST_VERSION] [RELEASE_TIMESTAMP])\n", GIMP_APP_VERSION); exit (EXIT_FAILURE); } program = argv[1]; pid = argv[2]; reason = argv[3]; message = argv[4]; error = g_strdup_printf ("%s: %s", reason, message); bt_file = argv[5]; g_file_get_contents (bt_file, &trace, NULL, NULL); if (trace == NULL || strlen (trace) == 0) exit (EXIT_FAILURE); if (argc == 8) { last_version = argv[6]; release_date = argv[7]; } gtk_init (&argc, &argv); dialog = gimp_critical_dialog_new (_("GIMP Crash Debug"), last_version, release_date ? g_ascii_strtoll (release_date, NULL, 10) : -1); gimp_critical_dialog_add (dialog, error, trace, TRUE, program, g_ascii_strtoull (pid, NULL, 10)); g_free (error); g_free (trace); g_signal_connect (dialog, "delete-event", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (dialog, "destroy", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show (dialog); gtk_main (); exit (EXIT_SUCCESS); } #ifdef G_OS_WIN32 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { return main (__argc, __argv); } #endif