diff --git a/src/Makefile.am b/src/Makefile.am index 24f4ffd..74e8aab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -167,7 +167,8 @@ wmaker_SOURCES += \ backend/wayland/wl_client.c \ backend/wayland/wl_icccm.c \ backend/wayland/wl_framebuf.c \ - backend/wayland/wl_atom.c + backend/wayland/wl_atom.c \ + backend/wayland/wl_signalfd.c endif if USE_NESTED_FUNC diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 5ec9c16..ce48e65 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -3111,91 +3111,6 @@ wl_display_default_screen(void) } -/* ------------------------------------------------------------------ */ -/* Phase 29+: signalfd-based signal handling */ -/* ------------------------------------------------------------------ */ - -/* - * wl_signalfd_handler -- called from within wl_event_loop_dispatch() when - * SIGTERM, SIGINT, or SIGHUP is pending on the signalfd. - * - * Running inside the event loop means we can safely call - * wl_display_terminate() without risking a re-entrant call into the Wayland - * event loop machinery, which is the failure mode of the traditional - * signal-handler → DispatchEvent → wl_display_terminate path. - */ -static int -wl_signalfd_handler(int fd, uint32_t mask, void *data) -{ - struct signalfd_siginfo info; - ssize_t n; - (void)mask; (void)data; - - n = read(fd, &info, sizeof(info)); - if (n != (ssize_t)sizeof(info)) - return 0; - - wwarning("wl_backend: signalfd received signal %u - terminating event loop", - (unsigned)info.ssi_signo); - - /* Set the exit state flag so post-loop cleanup paths see it. */ - SIG_WCHANGE_STATE(WSTATE_NEED_EXIT); - - /* Terminate the event loop. */ - wl_state.terminate = 1; - - return 0; -} - -#ifdef HAVE_INOTIFY -static void wl_handle_inotify_events(void) -{ - ssize_t eventQLength; - size_t i = 0; - char buff[(sizeof(struct inotify_event) + NAME_MAX + 1) * 5]; - int oneShotFlag = 0; - - eventQLength = read(w_global.inotify.fd_event_queue, buff, sizeof(buff)); - if (eventQLength < 0) { - wwarning(_("read problem when trying to get INotify event: %s"), strerror(errno)); - return; - } - - while (i < (size_t)eventQLength) { - struct inotify_event *pevent = (struct inotify_event *)&buff[i]; - - if (pevent->mask & IN_DELETE_SELF) { - wwarning(_("the defaults database has been deleted!")); - if (w_global.inotify.fd_event_queue >= 0) { - close(w_global.inotify.fd_event_queue); - w_global.inotify.fd_event_queue = -1; - } - } - if (pevent->mask & IN_UNMOUNT) { - wwarning(_("the unit containing the defaults database has been unmounted.")); - if (w_global.inotify.fd_event_queue >= 0) { - close(w_global.inotify.fd_event_queue); - w_global.inotify.fd_event_queue = -1; - } - wPreferences.flags.noupdates = 1; - } - /* React on IN_MOVED_TO (atomic rename — WMWritePropListToFile pattern) - * or IN_CLOSE_WRITE for direct writes. Skip temp files (they have - * a dot in their name like 'WindowMaker.XXXXXX'). */ - if (oneShotFlag == 0 && pevent->len > 0) { - const char *name = pevent->name; - int is_tempfile = (strchr(name, '.') != NULL); - if (((pevent->mask & IN_MOVED_TO) || - ((pevent->mask & IN_CLOSE_WRITE) && !is_tempfile))) { - wDefaultsCheckDomains(NULL); - oneShotFlag = 1; - } - } - i += sizeof(struct inotify_event) + pevent->len; - } -} -#endif - static void wl_event_loop_run(void) { diff --git a/src/backend/wayland/wl_signalfd.c b/src/backend/wayland/wl_signalfd.c new file mode 100644 index 0000000..26fa3d4 --- /dev/null +++ b/src/backend/wayland/wl_signalfd.c @@ -0,0 +1,106 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#ifdef HAVE_INOTIFY +#include +#include +#endif +#include +#include "../../screen.h" + +/* Forward declaration */ +void wDefaultsCheckDomains(void *arg); + +#include "wl_types.h" + + +/* ------------------------------------------------------------------ */ +/* Phase 29+: signalfd-based signal handling */ +/* ------------------------------------------------------------------ */ + +/* + * wl_signalfd_handler -- called from within wl_event_loop_dispatch() when + * SIGTERM, SIGINT, or SIGHUP is pending on the signalfd. + * + * Running inside the event loop means we can safely call + * wl_display_terminate() without risking a re-entrant call into the Wayland + * event loop machinery, which is the failure mode of the traditional + * signal-handler → DispatchEvent → wl_display_terminate path. + */ +int +wl_signalfd_handler(int fd, uint32_t mask, void *data) +{ + struct signalfd_siginfo info; + ssize_t n; + (void)mask; (void)data; + + n = read(fd, &info, sizeof(info)); + if (n != (ssize_t)sizeof(info)) + return 0; + + wwarning("wl_backend: signalfd received signal %u - terminating event loop", + (unsigned)info.ssi_signo); + + /* Set the exit state flag so post-loop cleanup paths see it. */ + SIG_WCHANGE_STATE(WSTATE_NEED_EXIT); + + /* Terminate the event loop. */ + wl_state.terminate = 1; + + return 0; +} + +#ifdef HAVE_INOTIFY +void wl_handle_inotify_events(void) +{ + ssize_t eventQLength; + size_t i = 0; + char buff[(sizeof(struct inotify_event) + NAME_MAX + 1) * 5]; + int oneShotFlag = 0; + + eventQLength = read(w_global.inotify.fd_event_queue, buff, sizeof(buff)); + if (eventQLength < 0) { + wwarning(_("read problem when trying to get INotify event: %s"), strerror(errno)); + return; + } + + while (i < (size_t)eventQLength) { + struct inotify_event *pevent = (struct inotify_event *)&buff[i]; + + if (pevent->mask & IN_DELETE_SELF) { + wwarning(_("the defaults database has been deleted!")); + if (w_global.inotify.fd_event_queue >= 0) { + close(w_global.inotify.fd_event_queue); + w_global.inotify.fd_event_queue = -1; + } + } + if (pevent->mask & IN_UNMOUNT) { + wwarning(_("the unit containing the defaults database has been unmounted.")); + if (w_global.inotify.fd_event_queue >= 0) { + close(w_global.inotify.fd_event_queue); + w_global.inotify.fd_event_queue = -1; + } + wPreferences.flags.noupdates = 1; + } + /* React on IN_MOVED_TO (atomic rename — WMWritePropListToFile pattern) + * or IN_CLOSE_WRITE for direct writes. Skip temp files (they have + * a dot in their name like 'WindowMaker.XXXXXX'). */ + if (oneShotFlag == 0 && pevent->len > 0) { + const char *name = pevent->name; + int is_tempfile = (strchr(name, '.') != NULL); + if (((pevent->mask & IN_MOVED_TO) || + ((pevent->mask & IN_CLOSE_WRITE) && !is_tempfile))) { + wDefaultsCheckDomains(NULL); + oneShotFlag = 1; + } + } + i += sizeof(struct inotify_event) + pevent->len; + } +} +#endif diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index fb4795e..8269338 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -499,3 +499,7 @@ void fb_attach_tree_listener(struct wl_frame_buf *fb); void fb_attach_scene_buf_listener(struct wl_frame_buf *fb); void wl_frame_paint_button(WCoreWindow *button, WTexture *texture, unsigned long color, WPixmap *image, int pushed); unsigned long wl_atom_intern(const char *name); + +/* Signalfd module declarations (extracted to wl_signalfd.c) */ +int wl_signalfd_handler(int fd, uint32_t mask, void *data); +void wl_handle_inotify_events(void);