https://github.com/swaywm/sway/issues/8673#issuecomment-2818260191 https://github.com/swaywm/sway/issues/8828#issuecomment-3290045852 --- common/stringop.c.orig 2025-04-20 11:31:10 UTC +++ common/stringop.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "list.h" #include "log.h" #include "stringop.h" @@ -319,7 +321,33 @@ bool expand_path(char **path) { memmove(ptr + 1, ptr, strlen(ptr) + 1); *ptr = '\\'; } - if (wordexp(*path, &p, 0) != 0 || p.we_wordv[0] == NULL) { + + // FreeBSD wordexp bug workaround: + // 1. Reset SIGCHLD handler + // 2. Run wordexp + // 3. Restore SIGCHLD handler and reap any processes that exited + struct sigaction prev_action; + struct sigaction new_action = { + .sa_flags = SA_RESETHAND, + }; + if (sigaction(SIGCHLD, &new_action, &prev_action) != 0) { + sway_log(SWAY_ERROR, "Restoring sigchild before wordexp failed"); + return false; + } + + int res = wordexp(*path, &p, 0); + + if (sigaction(SIGCHLD, &prev_action, NULL) != 0) { + sway_log(SWAY_ERROR, "Restoring sigchild after wordexp failed"); + } + + int status; + int wres; + do { + wres = waitpid(-1, &status, WNOHANG); + } while (wres > 0 || (wres == -1 && errno == EINTR)); + + if (res != 0 || p.we_wordv[0] == NULL) { wordfree(&p); return false; }