#734897 dovecot-core: dovecot does not assign stderr to /dev/null ???

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
#734897#5
Date:
2014-01-10 16:28:57 UTC
From:
To:
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;
...
###

#734897#10
Date:
2014-01-10 22:59:44 UTC
From:
To:
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');
}

##############

#734897#15
Date:
2017-09-15 09:02:02 UTC
From:
To:
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