[comp.unix.questions] fcntl

jpayne@rochester.ARPA (Jonathan Payne) (06/09/87)

(I don't know anything about this group - please reply to me, not
 the group, since I don't subscribe...)

I'm wondering about the use of FASYNC with fcntl on unix bsd systems.
tty(4) says that it only works for terminals, but I think it actually
works for sockets as well (I looked at the code).  Does anyone know
for sure?

My main question is this: Does the AT&T versions of UNIX (not v7, but
SysIII/V) have anything like FASYNC?  I'm trying to figure out how to do
asyncronous IO on various files (ttys, and pipes), and FASYNC with fcntl is
perfect, but I want to make sure it works for AT&T versions as well.

Thanks.

maart@cs.vu.nl (Maarten Litmaath) (09/10/88)

Isn't it a dubious feature that the PARENT should suffer if a CHILD decides
to set the FNDELAY flag of stdin?
It's an FCNTL() we're talking about, not an IOCTL()!
-- 
    Alles klar,                       |Maarten Litmaath @ Free U Amsterdam:
                   Herr Kommissar?    |maart@cs.vu.nl, mcvax!botter!maart

tanner@ki4pv.uucp (Dr. T. Andrews) (09/14/88)

In article <1380@solo7.cs.vu.nl>, maart@cs.vu.nl (Maarten Litmaath) writes:
) Isn't it a dubious feature that the PARENT should suffer if a CHILD
) decides) to set the FNDELAY flag of stdin? It's an FCNTL() we're
) talking about, not an IOCTL()!

Well, this is a good question.  Let's examine it.  First of all, note
that fcntl(2) operates on file descriptors (just like ioctl(2) does).
In many environments, it even offers several of the same sorts of
controls.  I don't see any moral difference between fcntl(2) and
ioctl(2), myself.  Thus, if ioctl() might cause a parent to suffer,
fcntl() may be expected to have a similar hazard.

Now, consider the effect proposed by maart@cs.vu.nl above: that the
parent's fd should not be affected by a child's action.  Mainly, the
"stty" command (remember: commands are run as children of shells) no
longer works.  It is no longer practical to change your tty modes.

You're stuck with whatever "getty" decided was best for you.
Alternatively, everything which might be used as a shell needs
to learn about the "stty" command, or else to set tty modes to
your satisfaction via the RPM instruction.
-- 
...!bikini.cis.ufl.edu!ki4pv!tanner  ...!bpa!cdin-1!cdis-1!ki4pv!tanner
or...  {allegra killer gatech!uflorida decvax!ucf-cs}!ki4pv!tanner

guy@gorodish.Sun.COM (Guy Harris) (09/15/88)

> Isn't it a dubious feature that the PARENT should suffer if a CHILD decides
> to set the FNDELAY flag of stdin?

Arguably.

> It's an FCNTL() we're talking about, not an IOCTL()!

The problem is that there are two sets of "file descriptor" flags: those stored
per-process, and those stored per "file table entry".  The "file table entry"
is shared by file descriptors passed to children, or created by "dup"; it holds
the seek pointer.

Unfortunately, the no-delay flag is a "file table entry" flag, not a
per-process flag.  The only per-process flag is the "close on exec" flag.
There exist "fcntl"s to manipulate both.

guy@gorodish.Sun.COM (Guy Harris) (09/16/88)

> Well, this is a good question.  Let's examine it.  First of all, note
> that fcntl(2) operates on file descriptors (just like ioctl(2) does).

Well, no.  "fcntl()" and "ioctl()" both take file descriptors as arguments.
However, they don't necessarily "operate on" those descriptors, in the sense
that they may fetch information from, or change the state of, objects to which
those descriptors refer, rather than the descriptors themselves.

"fcntl()" acts either on the file descriptor or on the file table
entry to which the descriptor refers (later UNIX releases also added other
functions, such as record locking, which don't fit this model, but you can
argue that they should have added a new call for those; 4.2BSD also
misimplemented no-delay mode as an "ioctl()", and had the "fcntl()" basically
do the "ioctl()" for you, but the original implementation of "fcntl()" in S3
got this right).

"ioctl()" generally acts on the object (file, device) to which the file table
entry referred to by the file descriptor refers (earlier UNIX releases stuck
functions such as FIOCLEX that operate on the descriptor and leave everything
below it alone, but you can argue that adding "fcntl()" for this function was
the right idea).

> In many environments, it even offers several of the same sorts of
> controls.

The only such control I can think of is FIOCLEX, and you can argue that, in a
pure sense, this shouldn't have been an "ioctl()" but should only have been an
"fcntl()".

> I don't see any moral difference between fcntl(2) and ioctl(2), myself.

See above.

> Thus, if ioctl() might cause a parent to suffer, fcntl() may be expected
> to have a similar hazard.

In general, both "fcntl()" and "ioctl()" *can* act on objects that are shared
by various file descriptors, so they *might* cause objects shared with a parent
to be affected.

However, while (with the exception of FIOCLEX, which could be argued shouldn't
have been an "ioctl()") "ioctl()" acts *only* on shared objects, "fcntl()"
*can* act on non-shared objects (the file descriptor itself).

Given that, the no-delay flag could have been a flag associated with the file
descriptor entry, in which case the parent will *not* be affected if a process
sets no-delay mode.

The argument you gave indicates that it is certainly *possible* for "fcntl()"s
setting no-delay mode to affect descriptors in the parent, but it basically
amounts to "this is how it was implemented"; it certainly was implemented that
way, but it didn't necessarily *have* to be implemented that way.  It could
conceivably have been implemented as a per-descriptor flag (similar to the
"close-on-exec" flag).

> Now, consider the effect proposed by maart@cs.vu.nl above: that the
> parent's fd should not be affected by a child's action.  Mainly, the
> "stty" command (remember: commands are run as children of shells) no
> longer works.  It is no longer practical to change your tty modes.

Well, no.  He specifically referred to "fcntl()"s done by the child, not
"ioctl()"s done by the child; there already exists a precedent for "fcntl()"s
that don't affect the parent (F_SETFD), and in fact there even exists a
precedent for "ioctl()"s that don't affect the parent (FIOCLEX).

Implementing no-delay mode as a per-descriptor flag would hardly imply that
"ioctl()"s such as the terminal "ioctl()"s would be obliged not to affect
parents of the process doing the "ioctl()".

maart@cs.vu.nl (Maarten Litmaath) (09/16/88)

In article <7034@ki4pv.uucp> tanner@ki4pv.uucp (Dr. T. Andrews) writes:
\In article <1380@solo7.cs.vu.nl>, maart@cs.vu.nl (Maarten Litmaath) writes:
\) Isn't it a dubious feature that the PARENT should suffer if a CHILD
\) decides) to set the FNDELAY flag of stdin? It's an FCNTL() we're
\) talking about, not an IOCTL()!
\
\Well, this is a good question.  Let's examine it.  First of all, note
\that fcntl(2) operates on file descriptors (just like ioctl(2) does).
\In many environments, it even offers several of the same sorts of
\controls.  I don't see any moral difference between fcntl(2) and
\ioctl(2), myself.

Aha! And where's the expected next statement: why has fcntl() been invented
in the first place?

\Now, consider the effect proposed by maart@cs.vu.nl above: that the
\parent's fd should not be affected by a child's action.

That's NOT what I said! My point was: let fcntl() handle the local (i.e.
per-process) effects, and leave the global effects to ioctl().
(Special attention to my .signature, please.)
-- 
    Alles klar,                       |Maarten Litmaath @ Free U Amsterdam:
                   Herr Kommissar?    |maart@cs.vu.nl, mcvax!botter!maart

scott@dtscp1.UUCP (Scott Barman) (09/17/88)

In article <68560@sun.uucp> guy@gorodish.Sun.COM (Guy Harris) writes:
>"fcntl()" acts either on the file descriptor or on the file table
>entry to which the descriptor refers (later UNIX releases also added other
>functions, such as record locking, which don't fit this model, but you can
>argue that they should have added a new call for those; 4.2BSD also
>misimplemented no-delay mode as an "ioctl()", and had the "fcntl()" basically
>do the "ioctl()" for you, but the original implementation of "fcntl()" in S3
>got this right).
Why is no-delay misimplemented in 4.2bsd ioctl, isn't turning on no-delay
an means of controlling i/o (which is where the i/o control system call
comes in)?

>"ioctl()" generally acts on the object (file, device) to which the file table
>entry referred to by the file descriptor refers (earlier UNIX releases stuck
>functions such as FIOCLEX that operate on the descriptor and leave everything
>below it alone, but you can argue that adding "fcntl()" for this function was
>the right idea).
Since when does ioctl act only on the object?  How much of the ioctl stuff
for terminal i/o do you think really some of that stuff gets to the actual
driver for manipulating the hardware?  The last I looked (which was not
that long ago), most of the ioctl's effect the tty software driver (input
or output canonization, etc.) and the only thing I had to worry about was
parity, baud rates, generating breaks (also catching them), and hangup
(setting baud rate to 0).  This has been the case since V7 (gee, am I
showing my age? :-).

>> I don't see any moral difference between fcntl(2) and ioctl(2), myself.
>See above.	(it was deleted here for brevity)
I do!  Why have a file control system call and an i/o control system call
when most i/o is on files anyway (a fundamental of Unix).  I can understand
different structures for the different types of ioctl's but not having
two systems calls and all the overhead involved--especially since the
call is written to know that the ioctl on a character device has to go to
the routine defined in the cdevsw table, etc.  Just more gunk and overhead
where it is not necessary.

>> Thus, if ioctl() might cause a parent to suffer, fcntl() may be expected
>> to have a similar hazard.
>In general, both "fcntl()" and "ioctl()" *can* act on objects that are shared
>by various file descriptors, so they *might* cause objects shared with a parent
>to be affected.
The only time that an ioctl or fcntl should effect a parent or other non-
related processes is when they have to effect shared resources.  The file
locking is a necessary shared resource that should go away when the child
processes ends.  Additionally, since terminals are shared resources (it
has only one tty structure leading to one piece of hardware, etc.), I can
see where changing it can effect all concerned.  However, anything else
should be considered a bug (feature? :-)

>However, while (with the exception of FIOCLEX, which could be argued shouldn't
>have been an "ioctl()") "ioctl()" acts *only* on shared objects, "fcntl()"
>*can* act on non-shared objects (the file descriptor itself).
It should not matter i/o control is i/o control no matter what the file
is since they are both accessed as files with the same system calls!  Any
distinction between them and you begin to lose that transparency that
is Unix.

-- 
scott barman		..!gatech!dtscp1!scott

guy@gorodish.Sun.COM (Guy Harris) (09/17/88)

> Why is no-delay misimplemented in 4.2bsd ioctl, isn't turning on no-delay
> an means of controlling i/o (which is where the i/o control system call
> comes in)?

No-delay is misimplemented in 4.2BSD "fcntl", not 4.2BSD "ioctl".  There is no
reason to make no-delay mode a property of the object to which a file
descriptor refers; the only way in which it should affect the behavior of the
object is that it should alter the behavior of the "read" and "write" system
calls.  As such, the way it could and should have been implemented would have
been to pass the current state of the no-delay flag to the device driver
"read" and "write" routines.  This means that if you set no-delay mode on one
file descriptor, it doesn't mean that accesses through an unrelated file
descriptor become no-delay accesses.

In fact, it arguably should have been a per-descriptor flag, rather than a
per-file-table-entry flag, so that if you set no-delay mode on one file
descriptor, it wouldn't even make accesses through a *related* file descriptor
become no-delay accesses (the standard input of a shell and of a command it
invokes are often related, which is why the problem that first triggered this
discussion occurs).

> Since when does ioctl act only on the object?  How much of the ioctl stuff
> for terminal i/o do you think really some of that stuff gets to the actual
> driver for manipulating the hardware?

As someone who has worked a fair bit with both the BSD and S5 tty drivers, and
who has written much of the SunOS 4.0 tty driver, I not only think that it all
gets to the actual driver, I *know* that it all gets to the actual driver.  Not
all of it affects the hardware, and not all of it is necessarily used by the
hardware driver; however, "the object" refers not to the serial port hardware,
it refers to the state maintained for that port by the line discipline as well.

In that sense, "ioctl" most definitely does act on the object.  The tty
"ioctl"s don't act on the data structures that represent the file descriptor,
nor do they act on the data structures that represent the file table entry.

> I do!  Why have a file control system call and an i/o control system call
> when most i/o is on files anyway (a fundamental of Unix).

Because file descriptors, file table entries, and the objects behind them are
distinct.  The "file control" system call is (or, at least, was) best called
the "file descriptor control" system call, since it only manipulated file
descriptors and file table entries.

> but not having two systems calls and all the overhead involved...

All *what* overhead?  Could you please quantify this "overhead"?

> especially since the call is written to know that the ioctl on a character
> device has to go to the routine defined in the cdevsw table, etc.

"fcntl" most definitely wass not originally written to know any of this.  The
original S5 "fcntl" call never looked at the inode pointer in the file table
entry, so it knew nothing whatsoever about the object referred to by the file
descriptor.  "ioctl" does what you discuss, but I fail to see why the fact that
it does all that has any relevance whatsoever to any of the points you may be
trying to make.
device driver routines; it just 

> The only time that an ioctl or fcntl should effect a parent or other non-
> related processes is when they have to effect shared resources.

Which was exactly my point; "fcntl()" can certainly set flags that belong only
to the file descriptor on which it acts, so the behavior the original person
appeared to want - namely, that no-delay mode *not* be shared between file
descriptors - could be implemented.

> It should not matter i/o control is i/o control no matter what the file
> is since they are both accessed as files with the same system calls!

I/O control is I/O control, but file descriptor control is file descriptor
control, and they are different.  *That* was the point being made, which you
appear to have completely missed.  You appear to be confusing file descriptors
with the object to which they refer.  File descriptors and file table entries
have their own state, which is distinct from the state maintained by the object
to which they refer.

tanner@ki4pv.uucp (Dr. T. Andrews) (09/18/88)

In article <1407@solo12.cs.vu.nl>, maart@cs.vu.nl (Maarten Litmaath) writes:
) Aha! And where's the expected next statement: why has fcntl() been
) invented in the first place?

Well, that's a good question.  Brief (nay, superficial) examination
of the manual gives no clue.

My suspicion is that it seemed to someone like a good idea at the
time.
-- 
...!bikini.cis.ufl.edu!ki4pv!tanner  ...!bpa!cdin-1!cdis-1!ki4pv!tanner
or...  {allegra killer gatech!uflorida decvax!ucf-cs}!ki4pv!tanner

gwyn@smoke.ARPA (Doug Gwyn ) (09/19/88)

In article <7039@ki4pv.uucp> tanner@ki4pv.uucp (Dr. T. Andrews) writes:
>In article <1407@solo12.cs.vu.nl>, maart@cs.vu.nl (Maarten Litmaath) writes:
>) Aha! And where's the expected next statement: why has fcntl() been
>) invented in the first place?
>My suspicion is that it seemed to someone like a good idea at the
>time.

It IS a good idea.  If you check out the internals of the kernel,
you'll find that ioctl is really supposed to be a hook into I/O
device drivers for things that don't fit the open/read/write/close
model.  fnctl on the other hand is for manipulating file table
entries and other similar actions that should not involve the
device driver at all.  Since both of them enter the kernel, either
COULD do anything at all, but a clean partitioning of function is
desirable.

freedman@granite.cr.bull.com (Jerome Freedman) (03/13/90)

  I know what the entry point(s) to ioctl are (I've seen
enough drivers but where are the fcntl entry points?
There is sort of an overlap there. Will a fcntl cause
a call to dev_ioctl?

                            Jerry Freedman,Jr

gwyn@smoke.BRL.MIL (Doug Gwyn) (03/15/90)

In article <1990Mar13.125755.9720@granite.cr.bull.com> freedman@granite.cr.bull.com (Jerome Freedman) writes:
>  I know what the entry point(s) to ioctl are (I've seen
>enough drivers but where are the fcntl entry points?
>There is sort of an overlap there. Will a fcntl cause
>a call to dev_ioctl?

Well, it's not supposed to -- fcntl() was introduced specifically
to play with the file table entries, which is something the device
driver is not supposed to know (or care) about.

guy@auspex.auspex.com (Guy Harris) (03/16/90)

 >>  I know what the entry point(s) to ioctl are (I've seen
 >>enough drivers but where are the fcntl entry points?
 >>There is sort of an overlap there. Will a fcntl cause
 >>a call to dev_ioctl?
 >
 >Well, it's not supposed to -- fcntl() was introduced specifically
 >to play with the file table entries, which is something the device
 >driver is not supposed to know (or care) about.

Unfortunately, both Berkeley and AT&T fairly quickly extended "fcntl()"
to do stuff other than monkey with file table entries.

In most cases, "fcntl()" will not call a device driver routine; there is
no "fcntl" entry point for a driver.

However, Berkeley saw fit to make no-delay I/O a property of the device,
rather than of the file table entry (it really should be a property of
the file descriptor, not the file table entry, but...), and the way they
do asynchronous I/O also makes it a property of the device.  This means
that in systems that support BSD-style no-delay and asynchronous I/O,
the "fcntl"s that turn on or off those modes cause FIONBIO and FIOASYNC
"ioctl"s, respectively, to be done. 

AT&T hasn't done anything like that in System V; "fcntl()" only reaches
its grubby paws down through the file system switch, not the device
driver switch....

vilva@csvax.csc.lsu.edu (Vilva Natarajan) (11/05/90)

I set my socket to non-blocking by doing this

	s = socket(...);

	fcntl(s,F_SETFL,FNDELAY)


Now after sometime I need to bring back my socket to a blocking mode.
How do I do it??

vilva@csvax.csc.lsu.edu