1

Onderwerp: Problemen met het monitoren van named pipes

Hi there,

Eerst maar eens uitleggen wat ik nu eigenlijk wil.
Ik wil dat een script (een perl script wat bij een radius event uitgevoerd wordt) een regel schrijft naar een named pipe.
Op de achtergrond moet een daemon draaien die deze pipe leest. Forks als hij een regel ontvangt (iets van MAC adress  gezien op poort x van switch y)  om hier iets mee te doen (de poort instellen).

Ik zit dus te knoeien met AnyEven:Handle om in een eventloop een pipe uit te lezen. Een voorbeeld gevonden wat ongeveer het framework zou kunnen zijn van wat ik wil doen.... alleen het werkt niet.

Allereerst heb ik een named pipe gemaakt met de opdracht "mkfifo test"

vervolgend voer ik het volgende script uit:

#! /usr/bin/perl -w

use strict;
use warnings;
use AnyEvent;
use AnyEvent::Handle;
use EV;

use autodie 'open';
use 5.010;

my @handles;

my $abort; 
$abort = AnyEvent->signal( signal => 'INT', cb => sub {
    say "Exiting.";
    $_->destroy for @handles;
    undef $abort; 
    # all watchers destroyed, event loop will return
});

my $handler; 
$handler = sub {
  my ( $h, $line, $eol ) =@_;
  my $name = $h->{name};
  say "$name: $line";
  $h->push_read( line => $handler );
};

my $file = './test';
#for my $file (@ARGV) {
  say "opening $file";
  open my $fh, '<', $file;
  my $h = AnyEvent::Handle->new( fh => $fh );
  $h->{name} = $file;
  $h->push_read( line => $handler );
#}

EV::loop;

als ik nu uitvoer stuur naar de pipe met:

pkn@sysop-2 ~/Documenten/scripts/perl/pipes $ ls -l > test

dan krijg ik dit als output:

opening ./test
./test: totaal 8
./test: prw-r--r-- 1 pkn pkn   0 okt 31 14:29 test
./test: -rwxr-xr-x 1 pkn pkn 696 okt 31 14:27 try1.pl
./test: -rwxr-xr-x 1 pkn pkn 477 okt 31 13:22 try2.pl
EV: error in callback (ignoring): AnyEvent::Handle uncaught error: Gebroken pijp at ./try1.p
l line 39.

de output van ls -l is dus over de pipe gezonden, meerdere regels worden afgehandeld. Maar op het eind van de input krijg ik een broken pipe. Na de broken pipe blijft het script aktief maar leest niet langer de pipe.
Wat ik verwacht had was dat het script gewoon weer was blijven wachten op nieuwe input.

2e ding wat me opviel
Voor de broken pipe kan ik de uitvoer niet onderbreken met ctrl-C, wat ik wel verwacht had ivm die abort handler.

Iemand die hier iets van weet?

Peter (aka Bilbo) geeft geen garantie op bestand- en padnamen, hij doet aan tab-completion.
http://bilbos-stekkie.com

2

Re: Problemen met het monitoren van named pipes

vergeet dit maar ff....
ben momenteel bezig dit op te lossen met IO:Socket::INET
maar daar heb ik ook een vraag over... blijf na een fork namelijk zitten met zombies... en snap niet goed waarom

post ik vanavond wel ff

Peter (aka Bilbo) geeft geen garantie op bestand- en padnamen, hij doet aan tab-completion.
http://bilbos-stekkie.com

3 Laatst bewerkt door QzZRBNMdJdsCmwx (02 Nov 2014 18:43:09)

Re: Problemen met het monitoren van named pipes

Reap je de zombies (zie waitpid)? Of het resultaat van forks negeren, wat je in C als volgt kunt doen:

signal(SIGCHLD, SIG_IGN);

Als je tussen processen wilt communiceren is 0mq (zeromq) misschien ook interessant. Sockets op steroiden.

4

Re: Problemen met het monitoren van named pipes

reapen.... dat had ik al eens ergens gezien... klinkt wel als iets wat ik zo willen big_smile

Peter (aka Bilbo) geeft geen garantie op bestand- en padnamen, hij doet aan tab-completion.
http://bilbos-stekkie.com

5 Laatst bewerkt door Peter (02 Nov 2014 19:49:36)

Re: Problemen met het monitoren van named pipes

Weet niet of het reapen is... maar ik heb dit gedaan:

#! /usr/bin/perl -w

use strict;
use sigtrap;
use IO::Socket::INET;

$| = 1;

my ($socket,$client_socket);
my ($peer_address,$peer_port);

$SIG{CHLD} = 'IGNORE';

$socket = IO::Socket::INET->new(
  LocalHost => '127.0.0.1',
  LocalPort => '33',
  Proto => 'tcp',
  Type => SOCK_STREAM,
  Reuse => 1,
  Listen => 10
) or die "Couldn't be a server on port 33: $!\n";

print "Waiting for connection on port 33. Server pid $$\n";

while($client_socket = $socket->accept()){
  my $pid;
  while (not defined ($pid = fork())){
    sleep 5;
  }
  if ($pid){
    close $client_socket;
  }else{
    $client_socket->autoflush(1);
    close $socket;
    &process();
  }
}

sub process {
  warn "client connected to pis $$\n";
  while (my $line = <$client_socket>){
    print "client => ", $line;
    print $client_socket "pid $$ > ", $line;
  }
  exit 0;
}

$socket->close();

Dit stukje:

$SIG{CHLD} = 'IGNORE';

had ik niet... en dat zorgt blijkbaar voor een automatische afsluiting van mijn child.
Er is geen interprocess communicatie oid nodig. Maakt me eigenlijk niets uit wat er met de child gebeurt. Als hij zijn ding maar doet.

Peter (aka Bilbo) geeft geen garantie op bestand- en padnamen, hij doet aan tab-completion.
http://bilbos-stekkie.com