nsxiv0e1a85d
Read all available inotify events
Loop reading from inotify fd in arl_handle(); requires non-blocking inotify fd.
+32 −27
1 file changed
- M autoreload_inotify.c +32 −27
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | * along with sxiv. If not, see <http://www.gnu.org/licenses/>. | |
| 17 | 17 | */ | |
| 18 | 18 | ||
| 19 | + | #include <errno.h> | |
| 19 | 20 | #include <stdlib.h> | |
| 20 | 21 | #include <string.h> | |
| 21 | 22 | #include <unistd.h> | |
| @@ -62,37 +63,41 @@ bool arl_handle(arl_t *arl, const char *filepath) | |||
| 62 | 63 | char *ptr; | |
| 63 | 64 | const struct inotify_event *event; | |
| 64 | 65 | ||
| 65 | − | ssize_t len = read(arl->fd, buf, sizeof(buf)); | |
| 66 | + | for (;;) { | |
| 67 | + | ssize_t len = read(arl->fd, buf, sizeof(buf)); | |
| 66 | 68 | ||
| 67 | − | if (len == -1) | |
| 68 | − | return false; | |
| 69 | − | ||
| 70 | − | for (ptr = buf; ptr < buf + len; ptr += sizeof(*event) + event->len) { | |
| 71 | − | event = (const struct inotify_event*) ptr; | |
| 72 | − | ||
| 73 | − | /* events from watching the file itself */ | |
| 74 | − | if (event->mask & IN_CLOSE_WRITE) { | |
| 75 | − | reload = true; | |
| 69 | + | if (len == -1) { | |
| 70 | + | if (errno == EINTR) | |
| 71 | + | continue; | |
| 72 | + | break; | |
| 76 | 73 | } | |
| 77 | − | if (event->mask & IN_DELETE_SELF) | |
| 78 | − | arl_setup_dir(arl, filepath); | |
| 79 | − | ||
| 80 | − | /* events from watching the file's directory */ | |
| 81 | − | if (event->mask & IN_CREATE) { | |
| 82 | − | char *fntmp = strdup(filepath); | |
| 83 | − | char *fn = basename(fntmp); | |
| 84 | − | ||
| 85 | − | if (STREQ(event->name, fn)) { | |
| 86 | − | /* this is the file we're looking for */ | |
| 74 | + | for (ptr = buf; ptr < buf + len; ptr += sizeof(*event) + event->len) { | |
| 75 | + | event = (const struct inotify_event*) ptr; | |
| 87 | 76 | ||
| 88 | − | /* cleanup, this has not been one-shot */ | |
| 89 | − | if (arl->watching_dir) { | |
| 90 | − | inotify_rm_watch(arl->fd, arl->wd); | |
| 91 | − | arl->watching_dir = false; | |
| 92 | − | } | |
| 77 | + | /* events from watching the file itself */ | |
| 78 | + | if (event->mask & IN_CLOSE_WRITE) { | |
| 93 | 79 | reload = true; | |
| 94 | 80 | } | |
| 95 | − | free(fntmp); | |
| 81 | + | if (event->mask & IN_DELETE_SELF) | |
| 82 | + | arl_setup_dir(arl, filepath); | |
| 83 | + | ||
| 84 | + | /* events from watching the file's directory */ | |
| 85 | + | if (event->mask & IN_CREATE) { | |
| 86 | + | char *fntmp = strdup(filepath); | |
| 87 | + | char *fn = basename(fntmp); | |
| 88 | + | ||
| 89 | + | if (STREQ(event->name, fn)) { | |
| 90 | + | /* this is the file we're looking for */ | |
| 91 | + | ||
| 92 | + | /* cleanup, this has not been one-shot */ | |
| 93 | + | if (arl->watching_dir) { | |
| 94 | + | inotify_rm_watch(arl->fd, arl->wd); | |
| 95 | + | arl->watching_dir = false; | |
| 96 | + | } | |
| 97 | + | reload = true; | |
| 98 | + | } | |
| 99 | + | free(fntmp); | |
| 100 | + | } | |
| 96 | 101 | } | |
| 97 | 102 | } | |
| 98 | 103 | return reload; | |
| @@ -101,7 +106,7 @@ bool arl_handle(arl_t *arl, const char *filepath) | |||
| 101 | 106 | void arl_init(arl_t *arl) | |
| 102 | 107 | { | |
| 103 | 108 | /* this needs to be done only once */ | |
| 104 | − | arl->fd = inotify_init(); | |
| 109 | + | arl->fd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK); | |
| 105 | 110 | arl->watching_dir = false; | |
| 106 | 111 | if (arl->fd == -1) | |
| 107 | 112 | error(0, 0, "Could not initialize inotify, no automatic image reloading"); | |