mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Add support for "e" flag (O_CLOEXEC) to 'open-file'.
* libguile/fports.c (scm_i_mode_to_open_flags): Add 'e' case. (scm_open_file_with_encoding): Document it. * test-suite/standalone/test-close-on-exec: New file. * test-suite/standalone/Makefile.am (check_SCRIPTS, TESTS): Add it. * doc/ref/api-io.texi (File Ports): Document it. * NEWS: Update.
This commit is contained in:
parent
3cd4881504
commit
a356ceebee
5 changed files with 59 additions and 2 deletions
7
NEWS
7
NEWS
|
@ -11,6 +11,13 @@ Changes in 3.0.9 (since 3.0.8)
|
|||
|
||||
* New interfaces and functionality
|
||||
|
||||
** `open-file' now supports an "e" flag for O_CLOEXEC
|
||||
|
||||
Until now, the high-level `open-file' facility did not provide a way to
|
||||
pass O_CLOEXEC to the underlying `open' call. It can now be done by
|
||||
appending "e" to the `mode' string passed as a second argument. See
|
||||
"File Ports" in the manual for more info.
|
||||
|
||||
** Abstract Unix-domain sockets are supported
|
||||
|
||||
It is now possible to create an AF_UNIX socket with a leading zero byte
|
||||
|
|
|
@ -996,6 +996,9 @@ Also, open the file using the binary-compatible character encoding
|
|||
@item +
|
||||
Open the port for both input and output. E.g., @code{r+}: open
|
||||
an existing file for both input and output.
|
||||
@item e
|
||||
Mark the underlying file descriptor as close-on-exec, as per the
|
||||
@code{O_CLOEXEC} flag.
|
||||
@item 0
|
||||
Create an "unbuffered" port. In this case input and output
|
||||
operations are passed directly to the underlying port
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright 1995-2004,2006-2015,2017-2020
|
||||
/* Copyright 1995-2004,2006-2015,2017-2020,2022
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of Guile.
|
||||
|
@ -208,6 +208,9 @@ scm_i_mode_to_open_flags (SCM mode, int *is_binary, const char *FUNC_NAME)
|
|||
flags |= O_BINARY;
|
||||
#endif
|
||||
break;
|
||||
case 'e':
|
||||
flags |= O_CLOEXEC;
|
||||
break;
|
||||
case '0': /* unbuffered: handled later. */
|
||||
case 'l': /* line buffered: handled during output. */
|
||||
break;
|
||||
|
@ -368,6 +371,9 @@ SCM_DEFINE (scm_i_open_file, "open-file", 2, 0, 1,
|
|||
"@item +\n"
|
||||
"Open the port for both input and output. E.g., @code{r+}: open\n"
|
||||
"an existing file for both input and output.\n"
|
||||
"@item e\n"
|
||||
"Mark the underlying file descriptor as close-on-exec, as per the\n"
|
||||
"@code{O_CLOEXEC} flag.\n"
|
||||
"@item 0\n"
|
||||
"Create an \"unbuffered\" port. In this case input and output\n"
|
||||
"operations are passed directly to the underlying port\n"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
##
|
||||
## Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
## 2011, 2012, 2013, 2014, 2020, 2021 Free Software Foundation, Inc.
|
||||
## 2011, 2012, 2013, 2014, 2020, 2021, 2022 Free Software Foundation, Inc.
|
||||
##
|
||||
## This file is part of GUILE.
|
||||
##
|
||||
|
@ -301,4 +301,7 @@ TESTS += test-stack-overflow
|
|||
check_SCRIPTS += test-out-of-memory
|
||||
TESTS += test-out-of-memory
|
||||
|
||||
check_SCRIPTS += test-close-on-exec
|
||||
TESTS += test-close-on-exec
|
||||
|
||||
EXTRA_DIST += ${check_SCRIPTS}
|
||||
|
|
38
test-suite/standalone/test-close-on-exec
Executable file
38
test-suite/standalone/test-close-on-exec
Executable file
|
@ -0,0 +1,38 @@
|
|||
#!/bin/sh
|
||||
exec guile -q -s "$0" "$@"
|
||||
!#
|
||||
|
||||
;;; Exercise the 'e' flag to 'open-file' (O_CLOEXEC).
|
||||
|
||||
(define file
|
||||
(string-append (or (getenv "TMPDIR") "/tmp")
|
||||
"/guile-test-close-on-exec-"
|
||||
(number->string (getpid)) ".txt"))
|
||||
|
||||
;;; Since fcntl(2) F_GETFD does not return flags such as O_CLOEXEC,
|
||||
;;; create a child process, call 'exec', and make sure it doesn't
|
||||
;;; inherit the file descriptor.
|
||||
(let ((port (open-file file "we")))
|
||||
(display "Hello!\n" port)
|
||||
(let ((pid (primitive-fork)))
|
||||
(if (zero? pid)
|
||||
(dynamic-wind
|
||||
(const #t)
|
||||
(lambda ()
|
||||
(execlp "guile" "guile" "-c"
|
||||
(object->string
|
||||
`(catch #t
|
||||
(lambda ()
|
||||
(fdopen ,(fileno port) "w")
|
||||
(primitive-exit 0))
|
||||
(lambda (key . args)
|
||||
(pk 'child-exception args)
|
||||
(if (and (eq? key 'system-error)
|
||||
(= EBADF (system-error-errno (cons key args))))
|
||||
(primitive-exit 1)
|
||||
(primitive-exit 2)))))))
|
||||
(lambda ()
|
||||
(primitive-exit 3)))
|
||||
(let ((status (pk 'child-status (cdr (waitpid pid)))))
|
||||
(false-if-exception (delete-file file))
|
||||
(exit (equal? (status:exit-val status) 1))))))
|
Loading…
Add table
Add a link
Reference in a new issue