23static int raised_signal;
24static int backtrace_done = 0;
26static int sighandler_backtrace(
void);
36static i3String *message_option_backtrace;
37static i3String *message_option_restart;
38static i3String *message_option_forget;
39static int dialog_width;
40static int dialog_height;
42static int border_width = 2;
49static int sighandler_backtrace(
void) {
50 char *tmpdir = getenv(
"TMPDIR");
55 pid_t pid_parent = getpid();
57 char *filename = NULL;
63 sasprintf(&filename,
"%s/i3-backtrace.%d.%d.txt", tmpdir, pid_parent, suffix);
67 pid_t pid_gdb = fork();
69 DLOG(
"Failed to fork for GDB\n");
71 }
else if (pid_gdb == 0) {
76 if (pipe(stdin_pipe) == -1) {
77 ELOG(
"Failed to init stdin_pipe\n");
80 if (pipe(stdout_pipe) == -1) {
81 ELOG(
"Failed to init stdout_pipe\n");
95 dup2(stdin_pipe[0], STDIN_FILENO);
96 dup2(stdout_pipe[1], STDOUT_FILENO);
98 char *pid_s, *gdb_log_cmd;
100 sasprintf(&gdb_log_cmd,
"set logging file %s", filename);
110 "-ex",
"set logging on",
114 execvp(args[0], args);
115 DLOG(
"Failed to exec GDB\n");
120 waitpid(pid_gdb, &status, 0);
123 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
124 DLOG(
"GDB did not run properly\n");
127 DLOG(
"GDB executed successfully, but no backtrace was generated\n");
138 message_intro =
i3string_from_utf8(
"i3 has just crashed. Please report a bug for this.");
139 message_intro2 =
i3string_from_utf8(
"To debug this problem, you can either attach gdb or choose from the following options:");
140 message_option_backtrace =
i3string_from_utf8(
"- 'b' to save a backtrace (requires gdb)");
142 message_option_forget =
i3string_from_utf8(
"- 'f' to forget the previous layout and restart i3");
146 dialog_width = width_longest_message + 2 * border_width + 2 * margin;
147 dialog_height = num_lines *
config.
font.
height + 2 * border_width + 2 * margin;
162 xcb_create_colormap(
conn, XCB_COLORMAP_ALLOC_NONE, dialog->
colormap,
root, visual);
169 mask |= XCB_CW_BACK_PIXEL;
173 mask |= XCB_CW_BORDER_PIXEL;
176 mask |= XCB_CW_OVERRIDE_REDIRECT;
180 mask |= XCB_CW_COLORMAP;
199 xcb_grab_keyboard(
conn,
false, dialog->
id, XCB_CURRENT_TIME, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
202 xcb_grab_pointer(
conn,
false, dialog->
id, XCB_NONE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, dialog->
id,
203 XCB_NONE, XCB_CURRENT_TIME);
216 xcb_destroy_window(
conn, dialog->
id);
244 int y = border_width + margin;
245 const int x = border_width + margin;
246 const int max_width = dialog->
dims.
width - 2 * x;
254 char *bt_color =
"#FFFFFF";
255 if (backtrace_done < 0) {
256 bt_color =
"#AA0000";
257 }
else if (backtrace_done > 0) {
258 bt_color =
"#00AA00";
271 uint16_t
state =
event->state;
276 state &= ~xcb_numlock_mask;
278 xcb_keysym_t sym = xcb_key_press_lookup_keysym(
keysyms, event,
state);
281 DLOG(
"User issued core-dump command.\n");
285 backtrace_done = sighandler_backtrace();
287 }
else if (sym ==
'r') {
290 }
else if (sym ==
'f') {
297 DLOG(
"i3 crashed. SIG: %d\n", sig);
299 struct sigaction action;
300 action.sa_handler = SIG_DFL;
302 sigemptyset(&action.sa_mask);
303 sigaction(sig, &action, NULL);
309 xcb_generic_event_t *event;
311 while ((event = xcb_wait_for_event(
conn))) {
313 int type = (
event->response_type & 0x7F);
319 if (((xcb_expose_event_t *)event)->count == 0) {
336 struct sigaction action;
339 action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
340 sigemptyset(&action.sa_mask);
343 if (sigaction(SIGQUIT, &action, NULL) == -1 ||
344 sigaction(SIGILL, &action, NULL) == -1 ||
345 sigaction(SIGABRT, &action, NULL) == -1 ||
346 sigaction(SIGFPE, &action, NULL) == -1 ||
347 sigaction(SIGSEGV, &action, NULL) == -1) {
348 ELOG(
"Could not setup signal handler.\n");
struct outputs_head outputs
static void sighandler_destroy_dialogs(void)
static void sighandler_create_dialogs(void)
static void sighandler_handle_key_press(xcb_key_press_event_t *event)
static void sighandler_setup(void)
static void sighandler_draw_dialog(dialog_t *dialog)
static void handle_signal(int sig, siginfo_t *info, void *data)
static void sighandler_handle_expose(void)
void setup_signal_handler(void)
Configured a signal handler to gracefully handle crashes and allow the user to generate a backtrace a...
void i3_restart(bool forget_layout)
Restart i3 in-place appends -a to argument list to disable autostart.
xcb_window_t create_window(xcb_connection_t *conn, Rect dims, uint16_t depth, xcb_visualid_t visual, uint16_t window_class, enum xcursor_cursor_t cursor, bool map, uint32_t mask, uint32_t *values)
Convenience wrapper around xcb_create_window which takes care of depth, generating an ID and checking...
xcb_visualid_t get_visualid_by_depth(uint16_t depth)
Get visualid with specified depth.
xcb_visualtype_t * get_visualtype_by_id(xcb_visualid_t visual_id)
Get visual type specified by visualid.
xcb_connection_t * conn
XCB connection and root screen.
xcb_key_symbols_t * keysyms
xcb_screen_t * root_screen
void draw_util_surface_init(xcb_connection_t *conn, surface_t *surface, xcb_drawable_t drawable, xcb_visualtype_t *visual, int width, int height)
Initialize the surface to represent the given drawable.
struct _i3String i3String
Opaque data structure for storing strings.
void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width)
Draw the given text using libi3.
int logical_px(const int logical)
Convert a logical amount of pixels (e.g.
void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface)
Destroys the surface.
void * scalloc(size_t num, size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
color_t draw_util_hex_to_color(const char *color)
Parses the given color in hex format to an internal color representation.
bool path_exists(const char *path)
Checks if the given path exists by calling stat().
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
void draw_util_rectangle(surface_t *surface, color_t color, double x, double y, double w, double h)
Draws a filled rectangle.
i3String * i3string_from_utf8(const char *from_utf8)
Build an i3String from an UTF-8 encoded string.
int predict_text_width(i3String *text)
Predict the text width in pixels for the given text.
void draw_util_clear_surface(surface_t *surface, color_t color)
Clears a surface with the given color.
#define TAILQ_FOREACH(var, head, field)
#define TAILQ_HEAD(name, type)
#define TAILQ_INSERT_TAIL(head, elm, field)
#define TAILQ_FIRST(head)
#define TAILQ_REMOVE(head, elm, field)
#define TAILQ_HEAD_INITIALIZER(head)
#define TAILQ_EMPTY(head)
#define TAILQ_ENTRY(type)
Stores a rectangle, for example the size of a window, the child window etc.
An Output is a physical output on your graphics driver.
bool active
Whether the output is currently active (has a CRTC attached with a valid mode)
Rect rect
x, y, width, height
int height
The height of the font, built from font_ascent + font_descent.