James K. Lowden
2014-09-19 19:38:19 UTC
unix(4) contains an "interesting" sentence:
"The received descriptor is a duplicate of the sender's
descriptor, as if it were created with a call to dup(2). Per-process
descriptor flags, set with fcntl(2), are not passed to a receiver."
because fcntl(2) doesn't define "per-process" descriptor flags. Does
the sentence mean "any flag set with fcntl", or are some flags
per-process? If the latter, is the reader supposed to be able to
determine which flags are per-process from the context?
McKusick distinguishes between a "file entry" describing an open file,
and a descriptor, which is an index into an array of references to file
entries. The descriptor array -- and hence each descriptor -- is
unique to each process, whereas many references to the file entry may
be created by fork() and dup(), and via unix domain sockets.
But fcntl(2) says it "provides for control over descriptors" when in
fact sometimes it updates or interrogates the file entry. Examples
include F_SETLK and (afaict) F_SETOWN. fcntl(2) does mention "flags
associated with the file descriptor", which I'm willing to believe are
"per-process". They are:
* the close-on-exec flag via F_SETFD
* the O_NONBLOCK, O_APPEND, and O_ASYNC flags via F_SETFL
(Can anyone explain why close-on-exec isn't just another option for
F_SETFL? I see that dup(2) preserves the F_SETFL flags but not
close-on-exec. Interesting choice....)
Do I have that aright? Are those the flags unix(4) means will not be
passed?
I'm also trying to reason about what happens when we "pass a
descriptor" over a unix domain socket (a misnomer, because we're
creating a new descriptor on an existing file entry). Something a lot
like dup(2) happens, and the new descriptor must be held by the kernel
for the benefit of the receiving process until it is received, at which
point it's installed in the process's descriptor table. Sort of like
fork in slow motion.
It's unclear to me why the sematics of descriptor-passing are different
in any way from dup(2). Are the differences considered a wart, or is
there a good reason for them?
FWIW, Linux doesn't have the same restriction: that page says, "The
passed file descriptors behave as though they have been created with
dup(2)."
Many thanks for your insight and elucidation.
--jkl
"The received descriptor is a duplicate of the sender's
descriptor, as if it were created with a call to dup(2). Per-process
descriptor flags, set with fcntl(2), are not passed to a receiver."
because fcntl(2) doesn't define "per-process" descriptor flags. Does
the sentence mean "any flag set with fcntl", or are some flags
per-process? If the latter, is the reader supposed to be able to
determine which flags are per-process from the context?
McKusick distinguishes between a "file entry" describing an open file,
and a descriptor, which is an index into an array of references to file
entries. The descriptor array -- and hence each descriptor -- is
unique to each process, whereas many references to the file entry may
be created by fork() and dup(), and via unix domain sockets.
But fcntl(2) says it "provides for control over descriptors" when in
fact sometimes it updates or interrogates the file entry. Examples
include F_SETLK and (afaict) F_SETOWN. fcntl(2) does mention "flags
associated with the file descriptor", which I'm willing to believe are
"per-process". They are:
* the close-on-exec flag via F_SETFD
* the O_NONBLOCK, O_APPEND, and O_ASYNC flags via F_SETFL
(Can anyone explain why close-on-exec isn't just another option for
F_SETFL? I see that dup(2) preserves the F_SETFL flags but not
close-on-exec. Interesting choice....)
Do I have that aright? Are those the flags unix(4) means will not be
passed?
I'm also trying to reason about what happens when we "pass a
descriptor" over a unix domain socket (a misnomer, because we're
creating a new descriptor on an existing file entry). Something a lot
like dup(2) happens, and the new descriptor must be held by the kernel
for the benefit of the receiving process until it is received, at which
point it's installed in the process's descriptor table. Sort of like
fork in slow motion.
It's unclear to me why the sematics of descriptor-passing are different
in any way from dup(2). Are the differences considered a wart, or is
there a good reason for them?
FWIW, Linux doesn't have the same restriction: that page says, "The
passed file descriptors behave as though they have been created with
dup(2)."
Many thanks for your insight and elucidation.
--jkl