Bradley,

> Yes. I have posted what I think is a single message's path through the
> logs. It does result in a bad file descriptor error. It is up at
> http://www.tux.org/~storm/files/amavisd.log.1

Thanks, the output from file(1) looks normal, yet your PerlIO or libc
returns incorrect status on reading the last line. I'm quite sure
it is related to the mentioned Perl I/O bug. It shows on some platforms,
and not on others. I'd suggest you try on a different OS platform,
perhaps as Gary suggests, or SUSE or whatever is supported by Zimbra.

As a quick-and-dirty workaround you may just comment out the
check for error status, although this way you'll never know
when a true error occurs. Just comment out the two lines:
    defined $ln || $!==0 || $!==EAGAIN
      or die "Error reading from file(1) utility: $!";


For experimenting, here is a small test program in Perl,
which mimics what amavisd does: forks a file(1) command
giving it some filename as argument, and reads output from
pipe line by line, printing each line, and checking status.
E.g.:  $ ./this-prog some-file.txt


#!/usr/bin/perl
use strict;
use IO::File;
use POSIX;

  my($cmd) = 'file';
  my(@args) = shift;

  my($pid); my($proc_fh) = IO::File->new;
  $pid = $proc_fh->open('-|');
  defined($pid) or die "run_command: can't fork: $!";
  if (!$pid) {  # child
    open_on_specific_fd(0, '/dev/null', &POSIX::O_RDONLY,0);
    open_on_specific_fd(2, '&1',        &POSIX::O_WRONLY,0);
    exec {$cmd} ($cmd,@args);
    die "Exec failed: $!";
    POSIX::_exit(8);  # avoid END and destructor processing
  }
  binmode($proc_fh) or die "Can't set pipe to binmode: $!";
  my($ln);
  for ($! = 0; defined($ln=$proc_fh->getline); $! = 0) {
    printf("result line from file(1): %s", $ln);
  }
  defined $ln || $!==0 || $!==EAGAIN
    or die "Error reading from file(1) utility: $!";

sub open_on_specific_fd($$$$) {
  my($fd_target,$fname,$flags,$mode) = @_;  my($fd_got);
  if ($fname =~ /^&=?(\d+)\z/) { $fd_got = $1 }  # fd directly specified
  if (!defined($fd_got) || $fd_got != $fd_target) {
    POSIX::close($fd_target);  # ignore error, we may have just closed a log
  }
  if (!defined($fd_got)) {  # file name was given, not a descriptor
    $fd_got = POSIX::open($fname,$flags,$mode);
    defined $fd_got or die "Can't open $fname: $!";
    $fd_got = 0 + $fd_got;  # turn into numeric, avoid: "0 but true"
  }
  if ($fd_got != $fd_target) {  # dup, ensuring we get a specified descriptor
    defined POSIX::dup2($fd_got,$fd_target)
      or "Can't dup2 from $fd_got to $fd_target: $!";
    if ($fd_got > 2)
      { defined POSIX::close($fd_got) or die "Can't close: $!" }
  }
}



Mark

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
AMaViS-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/amavis-user
AMaViS-FAQ:http://www.amavis.org/amavis-faq.php3
AMaViS-HowTos:http://www.amavis.org/howto/

Reply via email to