all repos — tint2 @ 40e01e2abf14b24ec0a9c9827c006de58ea66a1b

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

src/util/signals.c (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <errno.h>
#include <fcntl.h>
#include <glib.h>
#ifndef TINT2CONF
#ifdef HAVE_SN
#include <libsn/sn.h>
#endif
#endif
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

#include "common.h"
#include "panel.h"
#include "launcher.h"
#include "server.h"
#include "signals.h"

static sig_atomic_t signal_pending;

void signal_handler(int sig)
{
    // signal handler is light as it should be
    signal_pending = sig;
}

void reset_signals()
{
    for (int sig = 1; sig < 32; sig++) {
        signal(sig, SIG_DFL);
    }
    sigset_t signal_set;
    sigemptyset(&signal_set);
    sigprocmask(SIG_SETMASK, &signal_set, NULL);
}

#ifndef TINT2CONF
void init_signals()
{
    // Set signal handlers
    signal_pending = 0;

    reset_signals();

    struct sigaction sa_chld = {.sa_handler = SIG_IGN};
    sigaction(SIGCHLD, &sa_chld, 0);

    struct sigaction sa = {.sa_handler = signal_handler, .sa_flags = SA_RESTART};
    sigaction(SIGUSR1, &sa, 0);
    sigaction(SIGUSR2, &sa, 0);
    sigaction(SIGINT, &sa, 0);
    sigaction(SIGTERM, &sa, 0);
    sigaction(SIGHUP, &sa, 0);

#ifdef BACKTRACE_ON_SIGNAL
    struct sigaction sa_crash = {.sa_handler = crash_handler};
    sigaction(SIGSEGV, &sa_crash, 0);
    sigaction(SIGFPE, &sa_crash, 0);
    sigaction(SIGPIPE, &sa_crash, 0);
    sigaction(SIGBUS, &sa_crash, 0);
    sigaction(SIGABRT, &sa_crash, 0);
    sigaction(SIGSYS, &sa_crash, 0);
#endif
}

#ifdef BACKTRACE_ON_SIGNAL
void crash_handler(int sig)
{
    handle_crash(signal_name(sig));
    struct sigaction sa = {.sa_handler = SIG_DFL};
    sigaction(sig, &sa, 0);
    raise(sig);
}
#endif

int sigchild_pipe_valid = FALSE;
int sigchild_pipe[2];

static void sigchld_handler(int sig)
{
    if (!sigchild_pipe_valid)
        return;
    int savedErrno = errno;
    ssize_t unused = write(sigchild_pipe[1], "x", 1);
    (void)unused;
    fsync(sigchild_pipe[1]);
    errno = savedErrno;
}

void sigchld_handler_async()
{
    // Wait for all dead processes
    pid_t pid;
    int status;
    while ((pid = waitpid(-1, &status, WNOHANG)) != -1 && pid != 0) {
#ifdef HAVE_SN
        if (startup_notifications) {
            SnLauncherContext *ctx = (SnLauncherContext *)g_tree_lookup(server.pids, GINT_TO_POINTER(pid));
            if (ctx) {
                g_tree_remove(server.pids, GINT_TO_POINTER(pid));
                sn_launcher_context_complete(ctx);
                sn_launcher_context_unref(ctx);
            }
        }
#endif
        for (GList *l = panel_config.execp_list; l; l = l->next) {
            Execp *execp = (Execp *)l->data;
            if (g_tree_lookup(execp->backend->cmd_pids, GINT_TO_POINTER(pid)))
                execp_cmd_completed(execp, pid);
        }
    }
}

void handle_sigchld_events()
{
    if (sigchild_pipe_valid) {
        char buffer[1];
        while (read(sigchild_pipe[0], buffer, sizeof(buffer)) > 0) {
            sigchld_handler_async();
        }
    }
}

void init_signals_postconfig()
{
    gboolean need_sigchld = FALSE;
#ifdef HAVE_SN
    // Initialize startup-notification
    if (startup_notifications) {
        server.sn_display = sn_display_new(server.display, error_trap_push, error_trap_pop);
        server.pids = g_tree_new(cmp_ptr);
        need_sigchld = TRUE;
    }
#endif // HAVE_SN
    if (panel_config.execp_list)
        need_sigchld = TRUE;

    if (need_sigchld) {
        // Setup a handler for child termination
        if (pipe(sigchild_pipe) != 0) {
            fprintf(stderr, "tint2: Creating pipe failed.\n");
        } else {
            fcntl(sigchild_pipe[0], F_SETFL, O_NONBLOCK | fcntl(sigchild_pipe[0], F_GETFL));
            fcntl(sigchild_pipe[1], F_SETFL, O_NONBLOCK | fcntl(sigchild_pipe[1], F_GETFL));
            sigchild_pipe_valid = 1;
            struct sigaction act = {.sa_handler = sigchld_handler, .sa_flags = SA_RESTART};
            if (sigaction(SIGCHLD, &act, 0)) {
                perror("sigaction");
            }
        }
    }
}

void emit_self_restart(const char *reason)
{
    fprintf(stderr,
            YELLOW "%s %d: triggering tint2 restart, reason: %s" RESET "\n",
            __FILE__,
            __LINE__,
            reason);
    signal_pending = SIGUSR1;
}

int get_signal_pending()
{
    return signal_pending;
}
#endif