linux returns EAGAIN for closed ocserv interfaces

Nikos Mavrogiannopoulos nmav at gnutls.org
Fri Sep 26 11:57:50 PDT 2014


On Fri, 2014-09-26 at 13:33 +0100, David Woodhouse wrote:

> > > The close() system call should *never* fail to close the file
> > > descriptor. And as Linus points out, your force_close() hack is very
> > > broken in a threaded environment.
> > 
> > That doesn't matter much for ocserv as there are no multiple threads. It
> > was added as it looked reasonable for other OSes which may not behave as
> > Linux.
> 
> I'm not convinced there are any. I know of no other userspace which will
> retry a close() call. And it's hard to imagine how it could ever be
> necessary. The *flush* might fail, but closing the file descriptor is
> always easy enough because it just involves throwing away local state.
> 
> Also, we close all file descriptors when a process exits. If close() can
> fail, that makes a horrid mess of the task exit code path. I dread to
> think how this could ever be handled. I just don't think it can happen.

Niels, could you try this patch then (against master). If close() indeed
fails you should see "close failed:" in syslog. Otherwise we should
figure the real reason behind that issue.

btw. could that be reproduced the way David suggested?

regards,
Nikos

-------------- next part --------------
diff --git a/src/common.c b/src/common.c
index e88a560..faf65ff 100644
--- a/src/common.c
+++ b/src/common.c
@@ -75,6 +75,19 @@ static char tmp[32];
 	}
 }
 
+void force_close(int fd)
+{
+	int ret;
+	do {
+		ret = close(fd);
+		if (ret == -1) {
+			int e = errno;
+			syslog(LOG_ERR, "close failed: %s", strerror(e));
+			errno = e;
+		}
+	} while(ret == -1 && errno != EBADF);
+}
+
 ssize_t force_write(int sockfd, const void *buf, size_t len)
 {
 int left = len;
diff --git a/src/common.h b/src/common.h
index e17e908..57965fe 100644
--- a/src/common.h
+++ b/src/common.h
@@ -33,14 +33,7 @@ void *_talloc_size2(void *ctx, size_t size);
 #define PROTOBUF_ALLOCATOR(name, pool) \
 	ProtobufCAllocator name = {.alloc = _talloc_size2, .free = _talloc_free2, .allocator_data = pool}
 
-inline static
-void force_close(int fd)
-{
-	int ret;
-	do {
-		ret = close(fd);
-	} while(ret == -1 && errno != EBADF);
-}
+void force_close(int fd);
 
 ssize_t force_write(int sockfd, const void *buf, size_t len);
 ssize_t force_read(int sockfd, void *buf, size_t len);


More information about the openconnect-devel mailing list