- Package:
- dovecot-core
- Source:
- dovecot
- Description:
- secure POP3/IMAP server - core files
- Submitter:
- Laurent Declercq
- Date:
- 2017-09-15 09:12:04 UTC
- Severity:
- wishlist
Dear Maintainer, We have a control panel which does a restart of dovecot after installation. The problem is that if we catch stderr output, our installer hangs. This problem occurs only in Jessie. This bug seem really similar to the one as described there: https://bugzilla.redhat.com/show_bug.cgi?id=730746 When we do not catch stderr output from the command which is responsible to restart dovecot, all goes fine. Piece of code from our installer to let you understand (written in perl): ### ... # /usr/sbin/service dovecot restart $rs = execute( "$main::imscpConfig{'SERVICE_MNGR'} $self->{'config'}->{'DOVECOT_SNAME'} restart", \$stdout, \stderr ); ... ### ### ... my $sel = IO::Select->new(); my $pid; if(defined $stdout && defined $stderr) { $pid = open3(gensym, \*CATCHOUT, \*CATCHERR, $command); $sel->add(\*CATCHOUT, \*CATCHERR); } elsif(defined $stdout) { $pid = open3(gensym, \*CATCHOUT, ">&STDERR", $command); $sel->add(\*CATCHOUT); } elsif(defined $stderr) { $pid = open3(gensym, ">&STDOUT", \*CATCHERR, $command); $sel->add(\*CATCHERR); } else { system($command); return getExitCode($?); } while (my @ready = $sel->can_read()) { foreach my $fh (@ready) { if ($stderr && fileno($fh) == fileno(\*CATCHERR)) { $$stderr .= do { local $/; <$fh> }; } elsif($stdout) { $$stdout .= do { local $/; <$fh> }; } $sel->remove($fh) if eof($fh); } } waitpid($pid, 0) if $pid; ... ###
A typo error has been inserted in my report.
The right piece of code is:
######
sub execute($;$$)
{
my ($command, $stdout, $stderr) = @_;
fatal('$stdout must be a scalar reference') if $stdout && ref
$stdout ne 'SCALAR';
fatal('$stderr must be a scalar reference') if $stderr && ref
$stderr ne 'SCALAR';
debug("Execute $command");
my $sel = IO::Select->new();
my $pid;
if(defined $stdout && defined $stderr) {
$pid = open3(gensym, \*CATCHOUT, \*CATCHERR, $command);
$sel->add(\*CATCHOUT, \*CATCHERR);
} elsif(defined $stdout) {
$pid = open3(gensym, \*CATCHOUT, ">&STDERR", $command);
$sel->add(\*CATCHOUT);
} elsif(defined $stderr) {
$pid = open3(gensym, ">&STDOUT", \*CATCHERR, $command);
$sel->add(\*CATCHERR);
} else {
system($command);
return getExitCode($?);
}
while (my @ready = $sel->can_read()) {
foreach my $fh (@ready) {
if ($stderr && fileno($fh) == fileno(\*CATCHERR)) {
$$stderr .= do { local $/; <$fh> };
} elsif($stdout) {
$$stdout .= do { local $/; <$fh> };
}
$sel->remove($fh) if eof($fh);
}
}
waitpid($pid, 0) if $pid;
close(\*CATCHOUT) if defined $stdout;
close(\*CATCHERR) if defined $stderr;
chomp($$stdout ||= '');
chomp($$stderr ||= '');
getExitCode($?);
}
##############
sub restart
{
my $self = shift;
my $rs = $self->{'hooksManager'}->trigger('beforeMtaRestart');
return $rs if $rs;
my ($stdout, $stderr);
$rs = execute("$main::imscpConfig{'SERVICE_MNGR'}
$self->{'config'}->{'MTA_SNAME'} restart", \$stdout, \$stderr);
debug($stdout) if $stdout;
error($stderr) if $stderr && $rs > 1;
return $rs if $rs > 1;
$self->{'hooksManager'}->trigger('afterMtaRestart');
}
##############
Hi,
dovecot 2.2.x leaves stderr open by design, to allow the master process to log
errors after forking and before initializing the logging subsystem ,or in case
the logging subsystem fails:
commit 16e1bc9ee262481ec8bf6a1afbb539d1c2723912
Author: Timo Sirainen <tss@iki.fi>
Date: Mon Feb 18 07:12:44 2013 +0200
master: Don't close stderr. If log process fails at startup, the errors are logged there.
Since it's done by design - and I can see there are reasons to do so -
I'll mark this bug as wontfix. In any case, it is possible to spawn
dovecot (either directly, or via the initscript) and redirect stderr to
/dev/null using shell redirection if you wish to discard stderr.
Regards,
Apollon