fix
diff --git a/lib/fuse.c b/lib/fuse.c
index 0b31233..ec5ace9 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -1880,10 +1880,10 @@
size_t bufsize = fuse_chan_bufsize(ch);
struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
if (cmd != NULL) {
- int res = fuse_chan_receive(ch, cmd->buf, bufsize);
+ int res = fuse_chan_recv(ch, cmd->buf, bufsize);
if (res <= 0) {
free_cmd(cmd);
- if (res == -1)
+ if (res < 0 && res != -EINTR && res != -EAGAIN)
fuse_exit(f);
return NULL;
}
diff --git a/lib/fuse_kern_chan.c b/lib/fuse_kern_chan.c
index d58c8b2..fe7d252 100644
--- a/lib/fuse_kern_chan.c
+++ b/lib/fuse_kern_chan.c
@@ -16,26 +16,33 @@
static int fuse_kern_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
{
- ssize_t res = read(fuse_chan_fd(ch), buf, size);
- int err = errno;
+ int err;
+ ssize_t res;
struct fuse_session *se = fuse_chan_session(ch);
-
assert(se != NULL);
+
+ restart:
+ res = read(fuse_chan_fd(ch), buf, size);
+ err = errno;
+
if (fuse_session_exited(se))
return 0;
if (res == -1) {
- /* EINTR means, the read() was interrupted, ENOENT means the
- operation was interrupted */
- if (err == EINTR || err == ENOENT)
- return 0;
- /* ENODEV means we got unmounted, so we silently return failure */
- if (err != ENODEV)
+ /* ENOENT means the operation was interrupted, it's safe
+ to restart */
+ if (err == ENOENT)
+ goto restart;
+
+ /* Errors occuring during normal operation: EINTR (read
+ interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
+ umounted) */
+ if (err != EINTR && err != EAGAIN && err != ENODEV)
perror("fuse: reading device");
- return -1;
+ return -err;
}
if ((size_t) res < sizeof(struct fuse_in_header)) {
fprintf(stderr, "short read on fuse device\n");
- return -1;
+ return -EIO;
}
return res;
}
diff --git a/lib/fuse_loop.c b/lib/fuse_loop.c
index 1609bfc..6a6edaa 100644
--- a/lib/fuse_loop.c
+++ b/lib/fuse_loop.c
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <errno.h>
int fuse_session_loop(struct fuse_session *se)
{
@@ -23,16 +24,15 @@
}
while (!fuse_session_exited(se)) {
- res = fuse_chan_receive(ch, buf, bufsize);
- if (!res)
+ res = fuse_chan_recv(ch, buf, bufsize);
+ if (res == -EINTR)
continue;
- if (res == -1)
+ if (res <= 0)
break;
fuse_session_process(se, buf, res, ch);
- res = 0;
}
free(buf);
fuse_session_reset(se);
- return res;
+ return res < 0 ? -1 : 0;
}
diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c
index 540607b..16be149 100644
--- a/lib/fuse_loop_mt.c
+++ b/lib/fuse_loop_mt.c
@@ -74,12 +74,14 @@
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while (!fuse_session_exited(w->se)) {
- int res = fuse_chan_receive(w->prevch, buf, bufsize);
- if (!res)
+ int res = fuse_chan_recv(w->prevch, buf, bufsize);
+ if (res == -EINTR)
continue;
- if (res == -1) {
- fuse_session_exit(w->se);
- w->error = -1;
+ if (res <= 0) {
+ if (res < 0) {
+ fuse_session_exit(w->se);
+ w->error = -1;
+ }
break;
}
diff --git a/lib/fuse_session.c b/lib/fuse_session.c
index 4ea792a..8943204 100644
--- a/lib/fuse_session.c
+++ b/lib/fuse_session.c
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <errno.h>
struct fuse_session {
struct fuse_session_ops op;
@@ -143,11 +144,17 @@
return ch->se;
}
-int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
+int fuse_chan_recv(struct fuse_chan *ch, char *buf, size_t size)
{
return ch->op.receive(ch, buf, size);
}
+int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
+{
+ int res = fuse_chan_recv(ch, buf, size);
+ return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
+}
+
int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
{
return ch->op.send(ch, iov, count);
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 02ac176..2a8067a 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -96,6 +96,7 @@
fuse_setup_compat25;
fuse_unmount;
fuse_unmount_compat22;
+ fuse_chan_recv;
local:
*;