summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chat.h3
-rw-r--r--event.c49
2 files changed, 39 insertions, 13 deletions
diff --git a/chat.h b/chat.h
index f0d396d..e8f9378 100644
--- a/chat.h
+++ b/chat.h
@@ -20,6 +20,7 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdnoreturn.h>
#include <time.h>
#include <wchar.h>
@@ -43,7 +44,7 @@ void selfJoin(const char *join);
void eventWait(const char *argv[static 2]);
void eventPipe(const char *argv[static 2]);
-void eventLoop(void);
+noreturn void eventLoop(void);
struct Tag {
size_t id;
diff --git a/event.c b/event.c
index 9f8c35e..f5d1f32 100644
--- a/event.c
+++ b/event.c
@@ -14,16 +14,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <assert.h>
#include <err.h>
+#include <errno.h>
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
+#include <stdnoreturn.h>
#include <string.h>
#include <sys/wait.h>
#include <sysexits.h>
#include <unistd.h>
-#include <errno.h>
#include "chat.h"
@@ -86,8 +88,7 @@ static void pipeRead(void) {
}
}
-static void sigchld(int sig) {
- (void)sig;
+static void handleChild(void) {
int status;
pid_t pid = wait(&status);
if (pid < 0) err(EX_OSERR, "wait");
@@ -99,16 +100,31 @@ static void sigchld(int sig) {
spawn.wait = false;
}
-static void sigint(int sig) {
- (void)sig;
+static void handleInterrupt(void) {
input(TagStatus, "/quit");
uiExit();
exit(EX_OK);
}
-void eventLoop(void) {
- signal(SIGINT, sigint);
- signal(SIGCHLD, sigchld);
+static sig_atomic_t sig[NSIG];
+static void handler(int n) {
+ sig[n] = 1;
+}
+
+noreturn void eventLoop(void) {
+ sigset_t mask;
+ sigemptyset(&mask);
+ struct sigaction sa = {
+ .sa_handler = handler,
+ .sa_mask = mask,
+ .sa_flags = SA_RESTART,
+ };
+ sigaction(SIGCHLD, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+
+ struct sigaction curses;
+ sigaction(SIGWINCH, &sa, &curses);
+ assert(!(curses.sa_flags & SA_SIGINFO));
int irc = ircConnect();
@@ -118,6 +134,17 @@ void eventLoop(void) {
{ -1, POLLIN, 0 },
};
for (;;) {
+ if (sig[SIGCHLD]) handleChild();
+ if (sig[SIGINT]) handleInterrupt();
+ if (sig[SIGWINCH]) {
+ curses.sa_handler(SIGWINCH);
+ uiRead();
+ uiDraw();
+ }
+ sig[SIGCHLD] = 0;
+ sig[SIGINT] = 0;
+ sig[SIGWINCH] = 0;
+
nfds_t nfds = 2;
if (spawn.wait) nfds = 1;
if (spawn.pipe) {
@@ -127,10 +154,8 @@ void eventLoop(void) {
int ready = poll(fds, nfds, -1);
if (ready < 0) {
- if (errno != EINTR) err(EX_IOERR, "poll");
- uiRead();
- uiDraw();
- continue;
+ if (errno == EINTR) continue;
+ err(EX_IOERR, "poll");
}
if (fds[0].revents) ircRead();