moderated >> "Dup signals" in perlipc?

by Ilya Zakharevich » Wed, 30 Apr 2008 07:50:39 GMT

This is from perlipc:

while (1) {
unless (-p $FIFO) {
unlink $FIFO;
system('mknod', $FIFO, 'p')
&& die "can't mknod $FIFO: $!";
}

# next line blocks until there's a reader
open (FIFO, "> $FIFO") || die "can't write $FIFO: $!";
print FIFO "John Smith (smith\@host.org)\n", `fortune -s`;
close FIFO;
sleep 2; # to avoid dup signals
}

Eh??? What kind of a signal is a "dup signal", and why it may appear,
and why one would want to avoid it?

Thanks,
Ilya

P.S. I see that head1 "Named pipes" break inside the section on
signals...

P.P.S. Googling on
dup/signals fifo OR mkfifo -perlipc
finds only one obscure ref on sched.c, which I can't fully decipher...

moderated >> "Dup signals" in perlipc?

by mbe-usenet-29846 » Sun, 04 May 2008 16:23:44 GMT



I suppose the purpose of the sleep is simply to give the reading
process time to leave. Many programs have been known, e.g., to
lazily consume two end-of-file checks to end their input loop.
This would not hurt much on normal files but could trigger
another round of our writing loop here, if the reading process
is still busy on the other end when our process reopens the
named pipe. It is somewhat improbable since our stat system
call also needs to squeeze in between consecutive reads on the
other end, but not quite impossible.

I agree that the comment is not very intuitive. "To avoid
duplicate signatures" (not signals) would certainly be more
appropriate, since this example describes a signature generating
service.

-Martin

moderated >> "Dup signals" in perlipc?

by Ilya Zakharevich » Mon, 05 May 2008 05:40:00 GMT

[A complimentary Cc of this posting was sent to

< XXXX@XXXXX.COM >], who wrote in article < XXXX@XXXXX.COM >:




You mean that read() on a close()d file could re-open() it? Is the
semantic of *nix pipes really so broken? [So that one reader process
can read from many writers without reopen()?]

Moreover, (e.g., perl's) eof() just reads 1 char. Would not this just
block for these 2sec, thus beating the purpose of this sleep


There is (was ;-) no stat() call there; neither explicitly, nor in the
underlying implementation (one inside perl executable). Could you
please comment on this more?


I suspected that this is just an indication of yet another fishy bit
of *nix architecture of IPC...

(Since the system was not designed for multiprocessing, one is
forced to use some kind of "voodoo programming" [e.g., why 2sec,
and not 200sec?!] which increases the probability that the program
succeeds - without any guarantie of success.)

It is just not clear which particular piece of fishyness is fighted
with above, and I would like to know...

Thanks a lot,
Ilya

moderated >> "Dup signals" in perlipc?

by Martin Becker » Tue, 06 May 2008 15:28:14 GMT

lya Zakharevich < XXXX@XXXXX.COM > wrote:





Certainly not. In our scenario the reader would not have
closed the file, so there is no re-opening magic involved.

I do have to correct my statement, however, in that sleeping
will not cater for additional reading attempts after eof,
but rather help that eof is noticed at all. I'll elaborate
presently.


On system call level, end of file is notified through a read
operation returning a byte count of zero. Subsequent reads
may or may not get the same result, especially if the file is
actually a tty or a fifo with no physical end.

Closing the (last remaining) writing connection is a way of
telling "there is nothing more to read right now", which allows
an ongoing read operation to finish, even when no bytes have been
read so far, which is precisely what is needed to detect eof.
If, however, another writing connection is established and
firing away before the reading process gets a time slice from the
scheduler, the "nothing to read" condition will pass unnoticed.
The pipe will not be empty and disconnected anymore by the time
it is finally looked at.

A sleep, even for a short time, changes the process status to
"not ready" and thus greatly improves the chance of "ready"
processes, like the one with the pending read operation, to
be resumed first. Of course that is not guaranteed to work,
but seems good enough in practice.



Yes there was a stat call in the code part you quoted in
your original posting, in the guise of a "-p" file test:

Ilya> unless (-p $FIFO) {
Ilya> [...]
Ilya> }



Fishy indeed, as in "one man's shiny, slim and streamlined creature,
roaming the oceans with swift and elegant motions, is another man's
smelly thing the cat found in a dustbin".


The amount of two seconds might have been chosen because with
an accuracy of one second the actual sleeping time for sleep(1)
could be next to nothing in the "worst" case.


To sum it up, our short delay is supposed to keep the fifo long
enough in a "nothing to read" state for the current reader to
notice.

Admittedly, this is not a particularly nice example. As one
of the communicating parties is not supposed to be aware of
an active communication going on at all, there are not much
options for the protocol to deal with all sorts of special cases.

For a moment, I toyed with the idea of unlinking the fifo and
creating a new one each time through the loop, to deal with the
possibility of one reader getting more than one signature.
However, that would put the reader in danger of getting
blocked indefinitely (reading from a fifo no longer accessible
to anyone else), which would be far worse than the occasional
matter-of-seconds delay.

-Martin

moderated >> "Dup signals" in perlipc?

by Ilya Zakharevich » Sat, 12 Jul 2008 22:13:08 GMT

[A complimentary Cc of this posting was sent to
Martin Becker
< XXXX@XXXXX.COM >], who wrote in article < XXXX@XXXXX.COM >:


I see now what is EXACTLY the design problem with UNIX named pipes:
there is no way to create a "persistent EOF" condition, as it is
possible to do with TTYs and sockets.

To create EOF condition on a named pipe, the writer MUST close the
pipe, and wait until the reader reads from a closed pipe. However,
there no API to wait until this moment.

Contrast this with a TTY, where

perl -wle "sleep 10; 1 while <>"
then press
^D abc

^D creates a "persistent EOF" on the stream, and it does not matter
that "abc" is typed *before* "the other end of the TTY" makes a read.
(This works on DOSISH systems too [system is passing an actual ^Z
character, which is handled by the actual CRTL code].)

With sockets, AFAIK, it is slightly different: one creates a "session"
relationship between a writer and a reader (via bind()/accept()), then
one can create EOF by closing the last writer *in this session*; it is
- obviously - persistent, since there is no chance to write anything
after this ;-).

(BTW, this is how named pipes are implemented on DOSISH systems:
they also support a possibility of sessions.)

Thanks,
Ilya

Similar Threads

1. Signals interrupt accept() - bug in perldoc perlipc? - Perl

2. Regading 'perlipc'

Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Hi all,
  I would like to know if there is any possibilty to handle a situation where in while executing a perl script if i press a Control-C (or terminate the execution explicitly) then my code should be in a position to handle it and display a predefined message(or specifically execute predefined code for cleanup) and then actually exit the code execution.
  
Thanks in advance for the help.
  regards
Anand

 				
---------------------------------
 Here a new way to find what you're looking for - Yahoo! Answers 

3. perlipc doc / another race (?) - Perl

4. conflict between man perlipc and man perlfunc !?

5. perlipc bidirectional unix domain socket - Perl

6. Having trouble with dup and filehandles stored in a variable

I am having trouble getting duplication of STDOUT and STDERR to work
if I store filehandles in a variable.

I've read the documentation on open, IO::Handle, FileHandle,
perlfaq5. 

I lifted this code from perlfaq5

   #!/usr/bin/perl

   use strict;
   use diagnostics;

   open(OLDOUT, ">&STDOUT");
   open(OLDERR, ">&STDERR");

   open(STDOUT, "> /tmp/mystdout") || die "Can't redirect stdout";
   open(STDERR, ">&STDOUT")     || die "Can't dup stdout";

   select(STDERR); $| = 1;     # make unbuffered
   select(STDOUT); $| = 1;     # make unbuffered

   print STDOUT "stdout 1\n";  # this works for
   print STDERR "stderr 1\n";  # subprocesses too

   close(STDOUT);
   close(STDERR);

   open(STDOUT, ">&OLDOUT") || die "Can't reopen stdout: $!";
   open(STDERR, ">&OLDERR") || die "Can't reopen stderr: $!";;

   print STDOUT "stdout 2\n";
   print STDERR "stderr 2\n";


This works fine. If I try changing OLDOUT and OLDERR to $oldout and
$olderr, it doesn't work (perl 5.6.0)

   #!/usr/bin/perl

   use strict;
   use diagnostics;

   print STDOUT "Trying with variables\n";

   use Symbol;

   my $oldout = gensym();
   my $olderr = gensym();

   open($oldout, ">&STDOUT");
   open($olderr, ">&STDERR");

   open(STDOUT, "> /tmp/mystdout") || die "Can't redirect stdout";
   open(STDERR, ">&STDOUT")     || die "Can't dup stdout";

   select(STDERR); $| = 1;     # make unbuffered
   select(STDOUT); $| = 1;     # make unbuffered

   print STDOUT "stdout 3\n";  # this works for
   print STDERR "stderr 3\n";  # subprocesses too

   close(STDOUT);
   close(STDERR);

   print $oldout "Trying reopen of stdout\n";
   open(STDOUT, ">&$oldout") || die "Can't reopen stdout: $!";
   print $olderr "Trying reopen of stderr\n";
   open(STDERR, ">&$olderr") || die "Can't reopen stderr: $!";

   print STDOUT "stdout 4\n";
   print STDERR "stderr 4\n";

   print $oldout "stdout 5\n";
   print $olderr "stderr 5\n";

The program prints

Trying with variables
Trying reopen of stdout

If I trace in the debugger, the program exits right after

   open(STDOUT, ">&$oldout") || die "Can't reopen stdout: $!";

but I get no error indication.

What am I doing wrong?
-- 
Eric M. Boehm                  /"\  ASCII Ribbon Campaign
 XXXX@XXXXX.COM        \ /  No HTML or RTF in mail
                                X   No proprietary word-processing
Respect Open Standards         / \  files in mail

7. skip/delete lines with dup keys - Perl

8. Ignore errors inserting dup records?

I have a table "T" with an autonum primary key field "ID" and a
text/string field "v".  The field "v" is indexed and declared UNIQUE. 
Is there a syntax which will allow me to add records and ignore (or
not add) any which would violate the "unique" aspect of "v"?

Table "T":
ID v
----
1 I
2 am
3 the
4 walrus
5 oo
6 koo
7 katchoo

Given this table, I run this :
INSERT INTO T (v) VALUES ("The" , "walrus" , "was" , "Paul") ;

The insertion of "walrus" will fail because it already exists, and "v"
is indexed/no_dups.  I want the SQL to insert records for "The",
"was", and "Paul", and not error when in sees "walrus" already present
at record #4.

I'm doing this with Perl + DBI/DBD (not ODBC) talking to a MS-Access
.MDB file.

Thanks in advance.