From: brian@ilinx.wimsey.bc.ca (Brian J. Murrell)
Newsgroups: biz.sco.general
Subject: interesting system call, stopio
Date: 15 Sep 92 16:49:14 GMT
Organization: [resent by] The SCOGEN gateway and Propagation Society
Resent-From: mmdf@xenitec.on.ca
Submit-To: scogen@xenitec.on.ca
Cc: scoodt@imcon.wimsey.bc.ca
Precedence: bulk

I had an interesting experience with Hangups at the console that I feel is
worth sharing.

I wrote a c program which runs as a daemon.  It did not need to have a stdin
so I set stdin to /dev/null (open /dev/null and dup to fd 1).  This in itself
is not a problem.

I also have a printer set up under the lp sub-system which has an interface
script that does the "bsd lpr" thing, and therefore does not need a port (tty,
lp, etc) to send output to.  I therefore set up the port name as /dev/null,
which has been acceptable in the past.

But BEWARE, one should no longer do this!!

Ports which are attatched to printers by the lp sub-system will have side 
effects when used by another process.  The side effect here is caused by 
a system call "stopio".  I now quote a message from Bela Lubkin 
<belal@sco.COM>

But let's assume it *is* your process.  There's a system call in SCO
UNIX called stopio(S).  Calling stopio on a device causes any further
I/O to that device to be "poisoned": attempts to read, write or ioctl to
that device fail and send a SIGHUP to the process making the attempt.
Now, there are two things in the system which, by default, do stopio's.
One is the getty/init pair, which does stopio to a port before starting
getty.  The other is the print spooler, lpsched(ADM).  lpsched calls
stopio on the spooled-to device before starting the interface script.
In particular, if you have set up a networked printer, our standard
setup has you set them up with /dev/null as the spooled-to device.
Therefore, after printing to a network printer, the next time your
process attempt to do I/O, it gets a SIGHUP.

[ text about how to find printers attatched to /dev/null deleted]

Solution?  The best one is to disable stopio().  In 3.2v4 and ODT 2.0,
there is a kernel parameter, SECSTOPIO, which can be used to disable it.
It can't be disabled in 3.2v2 or ODT 1.1.

The next best solution is to use alternate "/dev/null" devices for your
network printers.  Create devices /dev/null2, /dev/null3, etc., one for
*each* networked printer.  These should have the same major number as
/dev/null, but minor numbers starting at 128 and increasing.  No two
printers should use the same major/minor numbers because they will
interfere with each other even if they don't interfere with your
process.  Note that stopio() works on a major/minor basis, not pathname
and not inode number; it is *not* sufficient just to make new
/dev/null2's with the same major/minor as /dev/null.  But minors 128-255
of the null device are guaranteed to always behave as /dev/null.

end of quoted message


I chose the latter method, as I felt the stopio was a good thing, and a 
"system feature" should not be sacrificed for an isolated (this particular
printer in my case) problem.

I just created a new node (mknod /dev/LaserIInull c 4 255) and changed my 
lp setup to relect the new "null" device I created, and everything is now
hunky-dorey.

MORAL:

Don't use /dev/null for printers in the lp sub-system, as /dev/null is a 
general use bit bucket to which many process read and write!!

Hope this helps,
brian

-- 
Brian J. Murrell                                        brian@ilinx.wimsey.bc.ca
InterLinx Support Services, Inc.                        uunet!van-bc!ilinx!brian
North Vancouver, B.C.
        Platform and Brand Independent UNIX Support - R3.2 - R4 - BSD