all repos — tint2 @ cd863c2819d9f1e96685a605b1d06c68e134a3cf

fork of the tint2 desktop panel for my custom setup - only minimized windows across all desktops for the taskbar

Restart on crash
o9000 mrovi9000@gmail.com
commit

cd863c2819d9f1e96685a605b1d06c68e134a3cf

parent

69f6f65db6a0a31be3b36a4942d873b0dca98820

6 files changed, 194 insertions(+), 11 deletions(-)

jump to
M src/systray/systraybar.csrc/systray/systraybar.c

@@ -28,6 +28,7 @@ #include <Imlib2.h>

#include <X11/extensions/Xdamage.h> #include <X11/extensions/Xcomposite.h> #include <X11/extensions/Xrender.h> +#include <unistd.h> #include "systraybar.h" #include "server.h"
M src/tint.csrc/tint.c

@@ -34,6 +34,8 @@ #include <signal.h>

#include <unistd.h> #include <sys/types.h> #include <pwd.h> +#include <time.h> +#include <sys/time.h> #ifdef HAVE_SN #include <libsn/sn.h>

@@ -75,6 +77,7 @@ XSettingsClient *xsettings_client = NULL;

timeout *detect_compositor_timer = NULL; int detect_compositor_timer_counter = 0; +double start_time = 0; void detect_compositor(void *arg) {

@@ -185,14 +188,9 @@ return NULL;

return pw->pw_dir; } -void crash_handler(int sig) +void dump_backtrace(int log_fd) { - char path[4096]; - sprintf(path, "%s/.tint2-crash.log", get_home_dir()); - int log_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0600); - log_string(log_fd, "Crashing with signal "); - log_string(log_fd, signal_name(sig)); - log_string(log_fd, "\nBacktrace:\n"); + log_string(log_fd, YELLOW "\nBacktrace:\n"); #ifdef ENABLE_LIBUNWIND unw_cursor_t cursor;

@@ -225,7 +223,61 @@ #else

log_string(log_fd, "Backtrace not supported on this system. Install libunwind or libexecinfo.\n"); #endif #endif - _exit(sig); + log_string(log_fd, RESET); +} + +// sleep() returns early when signals arrive. This function does not. +void safe_sleep(int seconds) +{ + double t0 = get_time(); + while (1) { + double t = get_time(); + if (t > t0 + seconds) + return; + sleep(1); + } +} + +void reexecute_tint2() +{ + write_string(2, GREEN "Attempting to restart tint2...\n" RESET); + // If tint2 cannot stay stable for 30 seconds, don't restart + if (get_time() - start_time < 30) { + write_string(2, GREEN "Not restarting tint2 since the uptime is too small.\n" RESET); + exit(-1); + } + safe_sleep(1); + close_all_fds(); + char *path = get_own_path(); + execlp(path, path, "-c", config_path, NULL); + exit(-1); +} + +void crash_handler(int sig) +{ + // We are going to crash, so restart the panel + char path[4096]; + sprintf(path, "%s/.tint2-crash.log", get_home_dir()); + int log_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0600); + log_string(log_fd, RED "tint2 crashed with signal " RESET); + log_string(log_fd, signal_name(sig)); + dump_backtrace(log_fd); + log_string(log_fd, RED "Please create a bug report with this log output.\n" RESET); + close(log_fd); + reexecute_tint2(); +} + +void x11_io_error(Display *display) +{ + // We are going to crash, so restart the panel + char path[4096]; + sprintf(path, "%s/.tint2-crash.log", get_home_dir()); + int log_fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0600); + log_string(log_fd, RED "tint2 crashed due to an X11 I/O error" RESET); + dump_backtrace(log_fd); + log_string(log_fd, RED "Please create a bug report with this log output.\n" RESET); + close(log_fd); + reexecute_tint2(); } void init(int argc, char *argv[])

@@ -373,6 +425,7 @@ fprintf(stderr, "tint2: could not open display.\n");

exit(1); } XSetErrorHandler((XErrorHandler)server_catch_error); + XSetIOErrorHandler((XIOErrorHandler)x11_io_error); server_init_atoms(); server.screen = DefaultScreen(server.display); server.root_win = RootWindow(server.display, server.screen);

@@ -1387,6 +1440,8 @@

int main(int argc, char *argv[]) { start: + start_time = get_time(); + init(argc, argv); init_X11_pre_config();
M src/util/common.csrc/util/common.c

@@ -32,6 +32,13 @@ #include <glib/gstdio.h>

#include "common.h" #include "../server.h" #include <sys/wait.h> +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <errno.h> +#include <sys/sysctl.h> #ifdef HAVE_RSVG #include <librsvg/rsvg.h>

@@ -620,3 +627,112 @@

return list; } #endif + +// Based loosely on close_allv from +// https://git.gnome.org/browse/glib/tree/gio/libasyncns/asyncns.c?h=2.21.0#n205 +// license: LGPL version 2.1 +// but with all the junk removed +// and +// https://opensource.apple.com/source/sudo/sudo-46/src/closefrom.c +// license: BSD +void close_all_fds() +{ + const int from_fd = 3; + +#ifdef __linux__ + DIR *d = opendir("/proc/self/fd"); + if (d) { + for (struct dirent *de = readdir(d); de; de = readdir(d)) { + if (de->d_name[0] == '.') + continue; + int fd = atoi(de->d_name); + if (fd < from_fd) + continue; + if (fd == dirfd(d)) + continue; + close(fd); + } + closedir(d); + return; + } +#endif + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) + closefrom(from_fd); + return; +#endif + +#if defined(__NetBSD__) + fcntl(from_fd, F_CLOSEM, 0); +#endif + + // Worst case scenario: iterate over all possible fds + int max_fd = sysconf(_SC_OPEN_MAX); + for (int fd = from_fd; fd < max_fd; fd++) { + close(fd); + } + + return; +} + +char* get_own_path() +{ + const int buf_size = 4096; + char *buf = calloc(buf_size, 1); + +#ifdef __linux__ + if (readlink("/proc/self/exe", buf, buf_size) > 0) + return buf; +#endif + +#if defined(__FreeBSD__) + int mib[4] = { + CTL_KERN, + KERN_PROC, + KERN_PROC_PATHNAME, + getpid() + }; + + size_t max_len = buf_size; + if (sysctl(mib, 4, buf, &max_len, NULL, 0) == 0) + return buf; +#endif + +#if defined(__DragonFly__) + if (readlink("/proc/curproc/file", buf, buf_size) > 0) + return buf; +#endif + +#if defined(__NetBSD__) + if (readlink("/proc/curproc/exe", buf, buf_size) > 0) + return buf; +#endif + +#if defined(__OpenBSD__) + int mib[4] = { + CTL_KERN, + KERN_PROC_ARGS, + getpid(), + KERN_PROC_ARGV + }; + + char *path = NULL; + size_t len; + if (sysctl(mib, 4, NULL, &len, NULL, 0) == 0 && len > 0) { + char **argv = malloc(len); + if (argv) { + if (sysctl(mib, 4, argv, &len, NULL, 0) == 0) { + path = realpath(argv[0], NULL); + } + } + free(argv); + } + if (path) { + free(buf); + return path; + } +#endif + + sprintf(buf, "tint2"); + return buf; +}
M src/util/common.hsrc/util/common.h

@@ -14,7 +14,7 @@ #include "area.h"

#define GREEN "\033[1;32m" #define YELLOW "\033[1;33m" -#define RED "\033[31m" +#define RED "\033[1;31m" #define BLUE "\033[1;34m" #define RESET "\033[0m"

@@ -107,5 +107,9 @@

#if !GLIB_CHECK_VERSION (2, 38, 0) #define g_assert_null(expr) g_assert((expr) == NULL) #endif + +void close_all_fds(); + +char* get_own_path(); #endif
M src/util/timer.csrc/util/timer.c

@@ -435,11 +435,16 @@ }

double profiling_get_time_old_time = 0; -double profiling_get_time() +double get_time() { struct timespec cur_time; clock_gettime(CLOCK_MONOTONIC, &cur_time); - double t = cur_time.tv_sec + cur_time.tv_nsec * 1.0e-9; + return cur_time.tv_sec + cur_time.tv_nsec * 1.0e-9; +} + +double profiling_get_time() +{ + double t = get_time(); if (profiling_get_time_old_time == 0) profiling_get_time_old_time = t; double delta = t - profiling_get_time_old_time;
M src/util/timer.hsrc/util/timer.h

@@ -69,4 +69,6 @@ // Returns the time difference in seconds between the current time and the last time this function was called.

// At the first call returns zero. double profiling_get_time(); +double get_time(); + #endif // TIMER_H