[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