inotify: properly handle multiple inotify events per read()

This commit is contained in:
Lennart Poettering 2010-10-13 02:34:00 +02:00
parent 52661efd21
commit f601daa701
3 changed files with 38 additions and 25 deletions

2
TODO
View File

@ -68,8 +68,6 @@
* ask-password tty timeout * ask-password tty timeout
* properly handle multiple inotify events per read() in path.c and util.c
* readahead: btrfs/LVM SSD detection * readahead: btrfs/LVM SSD detection
* document locale.conf, vconsole.conf and possibly the tempfiles.d and modules-load.d mechanism. * document locale.conf, vconsole.conf and possibly the tempfiles.d and modules-load.d mechanism.

View File

@ -453,7 +453,8 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
Path *p = PATH(u); Path *p = PATH(u);
int l; int l;
ssize_t k; ssize_t k;
struct inotify_event *buf = NULL; uint8_t *buf = NULL;
struct inotify_event *e;
PathSpec *s; PathSpec *s;
assert(p); assert(p);
@ -493,16 +494,22 @@ static void path_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
goto fail; goto fail;
} }
if ((size_t) k < sizeof(struct inotify_event) || e = (struct inotify_event*) buf;
(size_t) k < sizeof(struct inotify_event) + buf->len) {
log_error("inotify event too small.");
goto fail;
}
if (s->type == PATH_CHANGED && s->primary_wd == buf->wd) while (k > 0) {
path_enter_running(p); size_t step;
else
path_enter_waiting(p, false); if (s->type == PATH_CHANGED && s->primary_wd == e->wd)
path_enter_running(p);
else
path_enter_waiting(p, false);
step = sizeof(struct inotify_event) + e->len;
assert(step <= (size_t) k);
e = (struct inotify_event*) ((uint8_t*) e + step);
k -= step;
}
free(buf); free(buf);

View File

@ -2247,26 +2247,34 @@ int acquire_terminal(const char *name, bool fail, bool force, bool ignore_tiocst
assert(notify >= 0); assert(notify >= 0);
for (;;) { for (;;) {
struct inotify_event e; uint8_t inotify_buffer[sizeof(struct inotify_event) + FILENAME_MAX];
ssize_t l; ssize_t l;
struct inotify_event *e;
if ((l = read(notify, &e, sizeof(e))) != sizeof(e)) { if ((l = read(notify, &inotify_buffer, sizeof(inotify_buffer))) < 0) {
if (l < 0) { if (errno == EINTR)
continue;
if (errno == EINTR)
continue;
r = -errno;
} else
r = -EIO;
r = -errno;
goto fail; goto fail;
} }
if (e.wd != wd || !(e.mask & IN_CLOSE)) { e = (struct inotify_event*) inotify_buffer;
r = -EIO;
goto fail; while (l > 0) {
size_t step;
if (e->wd != wd || !(e->mask & IN_CLOSE)) {
r = -EIO;
goto fail;
}
step = sizeof(struct inotify_event) + e->len;
assert(step <= (size_t) l);
e = (struct inotify_event*) ((uint8_t*) e + step);
l -= step;
} }
break; break;