[rtems-libbsd commit] Fix reference counting for file descriptors

Sebastian Huber sebh at rtems.org
Fri Nov 10 12:00:20 UTC 2017


Module:    rtems-libbsd
Branch:    master
Commit:    72d5fa11a8e3a0e4640da289d76ae672eb070565
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=72d5fa11a8e3a0e4640da289d76ae672eb070565

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Nov 10 11:01:39 2017 +0100

Fix reference counting for file descriptors

Update #3132.

---

 freebsd/sys/kern/kern_event.c    |  2 ++
 freebsd/sys/kern/sys_pipe.c      |  6 ++++++
 freebsd/sys/kern/uipc_syscalls.c | 10 ++++++++++
 freebsd/sys/sys/file.h           |  7 +++++++
 freebsd/sys/sys/filedesc.h       |  5 ++++-
 5 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/freebsd/sys/kern/kern_event.c b/freebsd/sys/kern/kern_event.c
index ed1a9da..0a64adb 100644
--- a/freebsd/sys/kern/kern_event.c
+++ b/freebsd/sys/kern/kern_event.c
@@ -939,7 +939,9 @@ kern_kqueue(struct thread *td, int flags, struct filecaps *fcaps)
 #endif /* __rtems__ */
 
 	finit(fp, FREAD | FWRITE, DTYPE_KQUEUE, kq, &kqueueops);
+#ifndef __rtems__
 	fdrop(fp, td);
+#endif /* __rtems__ */
 
 	td->td_retval[0] = fd;
 	return (0);
diff --git a/freebsd/sys/kern/sys_pipe.c b/freebsd/sys/kern/sys_pipe.c
index 1636280..08dd619 100755
--- a/freebsd/sys/kern/sys_pipe.c
+++ b/freebsd/sys/kern/sys_pipe.c
@@ -485,16 +485,22 @@ kern_pipe(struct thread *td, int fildes[2], int flags, struct filecaps *fcaps1,
 	error = falloc_caps(td, &wf, &fd, flags, fcaps2);
 	if (error) {
 		fdclose(td, rf, fildes[0]);
+#ifndef __rtems__
 		fdrop(rf, td);
+#endif /* __rtems__ */
 		/* rpipe has been closed by fdrop(). */
 		pipeclose(wpipe);
 		return (error);
 	}
 	/* An extra reference on `wf' has been held for us by falloc_caps(). */
 	finit(wf, fflags, DTYPE_PIPE, wpipe, &pipeops);
+#ifndef __rtems__
 	fdrop(wf, td);
+#endif /* __rtems__ */
 	fildes[1] = fd;
+#ifndef __rtems__
 	fdrop(rf, td);
+#endif /* __rtems__ */
 
 	return (0);
 }
diff --git a/freebsd/sys/kern/uipc_syscalls.c b/freebsd/sys/kern/uipc_syscalls.c
index 3c6d7ef..62101b5 100644
--- a/freebsd/sys/kern/uipc_syscalls.c
+++ b/freebsd/sys/kern/uipc_syscalls.c
@@ -214,7 +214,9 @@ kern_socket(struct thread *td, int domain, int type, int protocol)
 			(void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td);
 		td->td_retval[0] = fd;
 	}
+#ifndef __rtems__
 	fdrop(fp, td);
+#endif /* __rtems__ */
 	return (error);
 }
 #ifdef __rtems__
@@ -616,8 +618,10 @@ done:
 		} else
 			*fp = NULL;
 	}
+#ifndef __rtems__
 	if (nfp != NULL)
 		fdrop(nfp, td);
+#endif /* __rtems__ */
 	fdrop(headfp, td);
 	return (error);
 }
@@ -840,15 +844,21 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol,
 		(void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td);
 		(void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td);
 	}
+#ifndef __rtems__
 	fdrop(fp1, td);
 	fdrop(fp2, td);
+#endif /* __rtems__ */
 	return (0);
 free4:
 	fdclose(td, fp2, rsv[1]);
+#ifndef __rtems__
 	fdrop(fp2, td);
+#endif /* __rtems__ */
 free3:
 	fdclose(td, fp1, rsv[0]);
+#ifndef __rtems__
 	fdrop(fp1, td);
+#endif /* __rtems__ */
 free2:
 	if (so2 != NULL)
 		(void)soclose(so2);
diff --git a/freebsd/sys/sys/file.h b/freebsd/sys/sys/file.h
index 18274d6..2adbd0a 100644
--- a/freebsd/sys/sys/file.h
+++ b/freebsd/sys/sys/file.h
@@ -413,6 +413,13 @@ rtems_bsd_fdrop(struct file *fp)
 	rtems_libio_iop_drop(&fp->f_io);
 }
 
+/*
+ * WARNING: fdalloc() and falloc_caps() do not increment the reference count of
+ * the file descriptor in contrast to FreeBSD.  We must not call the fdrop()
+ * corresponding to a fdalloc() or falloc_caps().  The reason for this is that
+ * FreeBSD performs a lazy cleanup once the reference count reaches zero.
+ * RTEMS uses the reference count to determine if a cleanup is allowed.
+ */
 #define	fdrop(fp, td) rtems_bsd_fdrop(fp)
 #endif /* __rtems__ */
 
diff --git a/freebsd/sys/sys/filedesc.h b/freebsd/sys/sys/filedesc.h
index b1c3e24..457898e 100644
--- a/freebsd/sys/sys/filedesc.h
+++ b/freebsd/sys/sys/filedesc.h
@@ -202,7 +202,6 @@ falloc_caps(struct thread *td, struct file **resultfp, int *resultfd,
 	*resultfp = rtems_bsd_iop_to_fp(iop);
 
 	if (iop != NULL) {
-		rtems_libio_iop_hold(iop);
 		iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
 		rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo);
 		*resultfd = rtems_libio_iop_to_descriptor(iop);
@@ -223,6 +222,10 @@ int	fdcheckstd(struct thread *td);
 #ifndef __rtems__
 void	fdclose(struct thread *td, struct file *fp, int idx);
 #else /* __rtems__ */
+/*
+ * WARNING: Use of fdrop() after fclose() corrupts the file descriptor.  See
+ * fdrop() comment.
+ */
 static inline void
 fdclose(struct thread *td, struct file *fp, int idx)
 {



More information about the vc mailing list