diff --git a/dat.h b/dat.h index 71066a2..b1f4c12 100644 --- a/dat.h +++ b/dat.h @@ -7,6 +7,13 @@ #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) +/* + * plan9port runs the note handlers for a note it goes on to ignore, and + * the process lives through it, so what strans announced must outlive + * such a note. A daemon that forks nothing gets only the one. + */ +#define notefatal(note) (strcmp(note, "sys: write on closed pipe") != 0) + /* A language id is the control code of the Ctrl key that selects it. */ enum { diff --git a/ibus.c b/ibus.c index 6a8e1b0..6c291af 100644 --- a/ibus.c +++ b/ibus.c @@ -83,9 +83,10 @@ unlinkaddr(void) } static int -addrnote(void*, char*) +addrnote(void*, char *note) { - unlinkaddr(); + if(notefatal(note)) + unlinkaddr(); return 0; } diff --git a/srv.c b/srv.c index 79f822f..1cd9b86 100644 --- a/srv.c +++ b/srv.c @@ -26,8 +26,8 @@ static int srvnote(void *v, char *note) { USED(v); - USED(note); - srvunlink(); + if(notefatal(note)) + srvunlink(); return 0; } diff --git a/tests/daemon_restart_test.c b/tests/daemon_restart_test.c index d4080c4..599bfd4 100644 --- a/tests/daemon_restart_test.c +++ b/tests/daemon_restart_test.c @@ -140,6 +140,38 @@ openpersistent(Test *t) return 1; } +/* + * plan9port ignores a broken pipe: the note handlers run and the daemon + * goes on serving, so the endpoints it announced must still be there. + */ +static int +survivenote(Test *t) +{ + struct stat st; + int fd, ok; + + if(kill(t->firstpid, SIGPIPE) < 0) + return fail("send a broken pipe to the first daemon: %s", + strerror(errno)); + pausems(200); + if(!daemonalive(&t->first)) + return fail("first daemon died of a broken pipe"); + if(lstat(t->l.socket, &st) < 0) + return fail("IPC socket taken by a note the daemon survived: %s", + strerror(errno)); + if(lstat(t->l.addrfile, &st) < 0) + return fail("IBus address taken by a note the daemon survived: %s", + strerror(errno)); + fd = connectsocket(t->l.socket, nowms() + Calltimeout); + if(fd < 0) + return fail("connect after a broken pipe: %s", strerror(errno)); + ok = ipcprobe(fd, "after a broken pipe"); + if(close(fd) < 0) + return fail("close the client opened after a broken pipe: %s", + strerror(errno)); + return ok; +} + static int hardcrash(Test *t) { @@ -329,6 +361,8 @@ runrestart(Test *t, char *program, char *mapdir) if(!waitready(&t->l, &t->first, t->firstaddress, sizeof t->firstaddress) || !privateaddress(t->firstaddress, t->firstpid) || !openpersistent(t)) return 0; + if(!survivenote(t)) + return 0; if(!hardcrash(t) || !waitipcclosed(t) || !waitbusclosed(t) || !checkstale(t) || !rejectold(t, "after hard crash")) return 0; @@ -367,6 +401,6 @@ main(int argc, char **argv) showerrors(&test.second); return 1; } - printf("daemon hard-crash endpoint recovery: ok\n"); + printf("daemon endpoints across a note and a hard crash: ok\n"); return 0; }