From bfcd38238b75faea59b3e461277510ff9031473f Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Fri, 10 Aug 2007 20:10:11 +0000 Subject: (shm_open): Use O_CLOEXEC is available. --- sysdeps/unix/sysv/linux/shm_open.c | 55 +++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 16 deletions(-) (limited to 'sysdeps') diff --git a/sysdeps/unix/sysv/linux/shm_open.c b/sysdeps/unix/sysv/linux/shm_open.c index 0d40632e5f..0628427680 100644 --- a/sysdeps/unix/sysv/linux/shm_open.c +++ b/sysdeps/unix/sysv/linux/shm_open.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000,2001,2002,2003,2004,2006 Free Software Foundation, Inc. +/* Copyright (C) 2000-2004,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -46,6 +46,11 @@ static const char defaultdir[] = "/dev/shm/"; __libc_once_define (static, once); +#if defined O_CLOEXEC && !defined __ASSUME_O_CLOEXEC +static bool have_o_cloexec; +#endif + + /* Determine where the shmfs is mounted (if at all). */ static void where_is_shmfs (void) @@ -160,6 +165,10 @@ shm_open (const char *name, int oflag, mode_t mode) __mempcpy (__mempcpy (fname, mountpoint.dir, mountpoint.dirlen), name, namelen + 1); +#ifdef O_CLOEXEC + oflag |= O_CLOEXEC; +#endif + /* And get the file descriptor. XXX Maybe we should test each descriptor whether it really is for a file on the shmfs. If this is what should be done the whole function @@ -168,23 +177,37 @@ shm_open (const char *name, int oflag, mode_t mode) fd = open (fname, oflag | O_NOFOLLOW, mode); if (fd != -1) { - /* We got a descriptor. Now set the FD_CLOEXEC bit. */ - int flags = fcntl (fd, F_GETFD, 0); - - if (__builtin_expect (flags, 0) >= 0) +#if !defined O_CLOEXEC || !defined __ASSUME_O_CLOEXEC +# ifdef O_CLOEXEC + if (have_o_cloexec <= 0) +# endif { - flags |= FD_CLOEXEC; - flags = fcntl (fd, F_SETFD, flags); - } - - if (flags == -1) - { - /* Something went wrong. We cannot return the descriptor. */ - int save_errno = errno; - close (fd); - fd = -1; - __set_errno (save_errno); + /* We got a descriptor. Now set the FD_CLOEXEC bit. */ + int flags = fcntl (fd, F_GETFD, 0); + + if (__builtin_expect (flags, 0) >= 0) + { +# ifndef O_CLOEXEC + if (have_o_cloexec == 0) + have_o_cloexec = (flags & FD_CLOEXEC) == 0 ? -1 : 1; + if (have_o_cloexec < 0) +# endif + { + flags |= FD_CLOEXEC; + flags = fcntl (fd, F_SETFD, flags); + } + } + + if (flags == -1) + { + /* Something went wrong. We cannot return the descriptor. */ + int save_errno = errno; + close (fd); + fd = -1; + __set_errno (save_errno); + } } +#endif } else if (__builtin_expect (errno == EISDIR, 0)) /* It might be better to fold this error with EINVAL since -- cgit v1.2.3