commit 6db1ccc

wf  ·  2026-03-28 12:59:48 +0000 UTC
parent 97031e7
IPC bug(fix)
4 files changed,  +80, -50
M README
M howl.c
M README
+1, -2
 1@@ -13,8 +13,7 @@ dependencies
 2 todo
 3 ----
 4 
 5- - fix IPC socket deadloop
 6- - configuration
 7+ - fix client segfault
 8  - document IPC interface
 9 
10 [1]: https://git.sr.ht/~shrub900/neuswc
+9, -9
 1@@ -14,18 +14,18 @@ ipc_msg(char **cmd) {
 2 	char msg[256];
 3 
 4 	memset(&addr, 0, sizeof(struct sockaddr_un));
 5-	addr.sun_family = AF_LOCAL;
 6+	addr.sun_family = AF_UNIX;
 7 	strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
 8 
 9-	csock = socket(AF_LOCAL, SOCK_STREAM, 0);
10-	if (csock == -1) {
11-		perror("couldn't open client socket");
12+	cfd = socket(AF_UNIX, SOCK_STREAM, 0);
13+	if (cfd == -1) {
14+		perror("couldn't open IPC socket");
15 		return;
16 	}
17 
18-	if (connect(csock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
19+	if (connect(cfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
20 		perror("couldn't connect to IPC socket");
21-		close(csock);
22+		close(cfd);
23 		return;
24 	}
25 
26@@ -35,11 +35,11 @@ ipc_msg(char **cmd) {
27 		strcat(msg, cmd[i]);
28 	}
29 
30-	if (send(csock, msg, strlen(msg), 0) == -1) {
31+	if (send(cfd, msg, strlen(msg), 0) == -1) {
32 		perror("couldn't send IPC message");
33 	}
34 
35-	close(csock);
36+	close(cfd);
37 }
38 
39 int
40@@ -52,7 +52,7 @@ main(int argc, char **argv) {
41 	int u_argc = argc - 2;
42 	char **u_argv = argv + 2;
43 
44-	for (int i = 0; i < (int)(sizeof commands / sizeof commands[0]); i++) {
45+	for (int i = 0; i < (sizeof commands / sizeof commands[0]); i++) {
46 		if (strcmp(commands[i].name, argv[1]) == 0) {
47 			if (commands[i].argc != u_argc) {
48 				fprintf(stderr, "wrong number of arguments for %s (need %d)\n", commands[i].name, commands[i].argc);
M howl.c
+68, -36
  1@@ -4,6 +4,7 @@
  2 #include <errno.h>
  3 #include <signal.h>
  4 #include <unistd.h>
  5+#include <fcntl.h>
  6 #include <getopt.h>
  7 #include <sys/socket.h>
  8 #include <sys/un.h>
  9@@ -42,67 +43,97 @@ static struct swc_screen_handler scr_handler = {
 10 
 11 static int
 12 handler(int fd, uint32_t mask, void *data) {
 13-	UNUSED(mask);
 14 	UNUSED(data);
 15 
 16-	_inf("handling :333333333333333333");
 17-
 18-	char buf[MAXSIZE];
 19-	ssize_t res = read(fd, buf, sizeof(buf) - 1);
 20+	if (mask & WL_EVENT_HANGUP) {
 21+		/* conn. closed */
 22+		_wrn("IPC socket connection closed prematurely: %s", strerror(errno));
 23+		return 0;
 24+	}
 25 
 26-	if (res < 0) {
 27-		_wrn("couldn't read from IPC socket: %s", strerror(errno));
 28-		return 1;
 29+	if (mask & WL_EVENT_ERROR) {
 30+		/* conn. error */
 31+		_wrn("IPC socket connection error: %s", strerror(errno));
 32+		return 0;
 33 	}
 34-	buf[res] = '\0';
 35 
 36-	_inf("read bullshit from socket: %s", buf);
 37+	if (mask & WL_EVENT_READABLE) {
 38+		if (fd == sfd) {
 39+			int afd = accept(sfd, NULL, NULL);
 40+			if (afd == -1) {
 41+				_wrn("couldn't accept incoming connection on IPC socket: %s", strerror(errno));
 42+				return 0;
 43+			}
 44 
 45-	char *tok;
 46-	int argc = 0;
 47-	char **argv;
 48+			char buf[MAXSIZE];
 49+			ssize_t n;
 50 
 51-	tok = strtok(buf, " ");
 52-	argv[argc] = tok;
 53-	argc++;
 54+			if ((n = read(afd, buf, sizeof(buf) - 1)) < 0) {
 55+				/* read error */
 56+				_wrn("couldn't read from IPC socket: %s", strerror(errno));
 57+				return 0;
 58+			}
 59 
 60-	while (tok != NULL) {
 61-		argv[argc] = tok;
 62-		argc++;
 63-		tok = strtok(NULL, " ");
 64-	}
 65+			if (n == 0) {
 66+				/* EOF */
 67+				_wrn("unexpected EOF on IPC socket: %s", strerror(errno));
 68+				return 0;
 69+			}
 70 
 71-	for (int i = 0; i < (sizeof commands / sizeof commands[0]); i++) {
 72-		if (strcmp(commands[i].name, argv[0]) == 0) {
 73-			argv++;
 74-			commands[i].fn(argv);
 75-			if (commands[i].config) reload_config();
 76+			if (n > 0) {
 77+				int argc = 0;
 78+				char *argv[64], *tok = NULL;
 79+
 80+				buf[n] = '\0';
 81+				while (buf[n-1] == '\r' || buf[n-1] == '\n' || buf[n-1] == ' ')
 82+					buf[n-1] = '\0';
 83+
 84+				tok = strtok(buf, " ");
 85+				while (tok != NULL && argc < 63) {
 86+					argv[argc++] = tok;
 87+					tok = strtok(NULL, " ");
 88+				}
 89+				argv[argc] = NULL;
 90+
 91+				if (argc == 0) return 0;
 92+
 93+				for (int i = 0; i < (sizeof commands / sizeof commands[0]); i++) {			
 94+					if (strcmp(commands[i].name, argv[0]) == 0) {
 95+						commands[i].fn(argv + 1);
 96+						if (commands[i].config) reload_config();
 97+						return 0;
 98+					}
 99+				}
100+				_wrn("no such command %s", argv[0]);
101+			}
102+			close(afd);
103+			return 0;
104 		}
105 	}
106 
107-	return 0;
108+	return 0; /* NOTREACHED */
109 }
110 
111 static void
112 setup_ipc(void) {
113 	struct sockaddr_un addr;
114 
115-	ssock = socket(AF_LOCAL, SOCK_STREAM, 0);
116-	if (ssock == -1)
117+	sfd = socket(AF_UNIX, SOCK_STREAM, 0);
118+	if (sfd == -1)
119 		_err(1, "couldn't open IPC socket: %s", strerror(errno));
120 
121 	memset(&addr, 0, sizeof(addr));
122-	addr.sun_family = AF_LOCAL;
123+	addr.sun_family = AF_UNIX;
124 	strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
125 
126 	unlink(SOCK_PATH);
127-	if (bind(ssock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
128+	if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
129 		_err(1, "couldn't bind IPC socket: %s", strerror(errno));
130 
131-	if (listen(ssock, 5) == -1)
132+	if (listen(sfd, 5) == -1)
133 		_err(1, "couldn't listen on IPC socket: %s", strerror(errno));
134 
135-	wl_event_loop_add_fd(wm.loop, ssock, WL_EVENT_READABLE, handler, NULL);
136+	wl_event_loop_add_fd(wm.loop, sfd, WL_EVENT_READABLE | WL_EVENT_HANGUP | WL_EVENT_ERROR, handler, NULL);
137 
138 	_inf("set up IPC socket");
139 }
140@@ -113,8 +144,6 @@ sig_handler(int s) {
141 	if (wm.dpy) {		
142 		swc_finalize();
143 		wl_display_terminate(wm.dpy);
144-		close(ssock);
145-		unlink(SOCK_PATH);
146 	}
147 }
148 
149@@ -199,13 +228,16 @@ setup(void) {
150 	signal(SIGINT,  sig_handler);
151 	signal(SIGTERM, sig_handler);
152 	signal(SIGQUIT, sig_handler);
153+
154+	free(conf_path);
155 }
156 
157 static void
158 cleanup(void) {
159 	swc_finalize();
160 	wl_display_destroy(wm.dpy);
161-	close(ssock);
162+	close(sfd);
163+	unlink(SOCK_PATH);
164 }
165 
166 static void
+2, -3
 1@@ -7,9 +7,8 @@
 2 #define SOCK_PATH  "/tmp/.howl.sock"
 3 #define MAXSIZE    256
 4 
 5-/* IPC socket */
 6-static int ssock;
 7-static int csock;
 8+static int sfd;
 9+static int cfd;
10 
11 extern void _inf(const char *, ...);
12 extern void _wrn(const char *, ...);