[solved] perl, FCGI.pm, fork(), pipe() 2>&1

Kérem szépen, valaki Perl mágus világosítson fel mit rontok el az alábbi kódban!
Nincs kimenet (upstream prematurely closed FastGCI stdout... üzenet az nginx-tõl), SIGPIPE-pal/Illegal seek-kel elhal valami, meg ilyet is dob:

Not a GLOB reference at /usr/lib/perl5/FCGI.pm line 125

Valahogy az FCGI modulhoz lesz köze, mert csupán a do_request-et futtatva simán teszi, amire kérem: a futtatandó cgi (@app) stderr-ja is az stdout-ba menjen.
Ennyit szeretnék mindössze. Próbalkoztam az IPC::Open3-mal, de arra meg Broken pipe-ot dob! A pájpolós+forkolós rész helyett ez volt:


    $appPID = open3(\*reader, \*writer, 0, @app);
    print {*writer} <STDIN>;
    close *writer;
    print <reader>;
    waitpid ...

Érdekes ugyanakkor, hogy IPC::Open2 minden exception nélkül mũködött, csakhát az különhagyja az stderr-t.

a lényeges részek tehát:


use FCGI;
$\=$/=undef;
$request = FCGI::Request();

sub do_request() {
    push my @app, qw(sudo -E -u anybody /path/to/anyscript.sh);

	pipe PR, CW;  # parent reader, child writer
	pipe CR, PW;  # child reader, parent writer
	my $appPID = fork;
	if($appPID == 0) {
		# Child.
		close CR;
		close CW;
		open STDIN, "<&=PR";
		open STDOUT, ">&=PW";
		open STDERR, ">&=PW";
		exec @app;
		exit $?;
	}

	# Parent.
	close PR;
	close PW;
	print CW <STDIN>;
	close CW;
	print <CR>;

    waitpid($appPID, 0);
    $app_exit_status = $? >> 8;

    $request->Finish();
}

while($handling_request = ($request->Accept() >= 0)) {
    &do_request;
}

Így néz ki, ahogy nem fogom megcsinálni:

print `/path/to/anyscript.sh 2>&1`

;

--- edit ---

... és így, ahogyan igen: http://hup.hu/node/117836#comment-1507958

Hozzászólások

GLOB reference error

NOTE: This issue was fixed in Movable Type 5.
Not a GLOB reference at /usr/lib/perl5/FCGI.pm line 125.

If you are experiencing the above error when rebuilding single entries, ensure that the '''[[LaunchBackgroundTasks]]''' configuration option is either set to 0 or removed entirely from your '''mt-config.cgi''' file.

FCGI.PL,v 1.37 verziójában találtam: vajon lehet hozzá köze?

# Some things (e.g. IPC::Run) use fileno to determine if a filehandle is open,
# so we return a defined, but meaningless value. (-1 being the error return
# value from the syscall in c, meaning it can never be a valid fd no)
# Probably a better alternative would be to return the fcgi stream fd.
sub FILENO { -1 }

~~~~~~~~
http://www.youtube.com/watch?v=VbUVqODL1nE

Két nap hosszas próbálgatás után megoldottnak látszik a program:
A kód alap szerkezete jó, csak az FCGI modul is babrál a háttérben a file descriptorokkal, ezért nem kaptam a várt eredményt.
Megoldásnak azt találtam, hogy fork-olás elõtt Detach-olom a processzt az FCGI-tõl (ez pontosan nem tudom mit csinál, de a nevébõl arra következtettem, hogy a "mintha nem is lenne FCGI" környezetet állítja vissza)
a kód most:


use FCGI;
$0 = "fcgid";
$|=1; select STDERR; $|=1; select STDOUT;
$/=undef;    # egyszerre be tudjuk olvasni az STDIN-t
$request = FCGI::Request();

sub do_request() {

    push my @app, qw(sudo -E -u anybody /path/to/anyscript.sh);

    $POST_BODY = <STDIN>;
    $request->Detach();

	pipe KID, PAR;
	my $appPID = open(APP, "-|");
	if(!defined $appPID) {
		$request->Attach();
		print STDERR "fork: Resource not avilable.\n";
		goto FIN;
	}
	elsif($appPID == 0) {
		# Child.
		close PAR;
		open STDIN, "<&=KID";
		open STDERR, ">&=STDOUT";
		if(!-x $app) {
			print STDERR "Status: 500\r\nContent-Type: text/plain\r\n\r\n$0: ",$ENV{"SCRIPT_NAME"},": Could not execute.\n";
			exit;
		}
		exec @app;
		exit $?;
	}
	else {
		# Parent.
		close KID;
		print PAR $POST_BODY;
		close PAR;
		$request->Attach();
		print <APP>;
		print "\r\n" if tell APP == 0;  # nginx 502-t dob ha nem ad semmit a fascgi upstream
	}

    $child_status = waitpid($appPID, 0);
    if($child_status > 0) {
	$app_exit_status = $? >> 8;
	print STDERR "$app: exitcode: $app_exit_status\n" if $app_exit_status != 0;
    } else {
    	print STDERR "$app: nonexistent child process.\n";
    }

    FIN:
    $request->Finish();
}


while($handling_request = ($request->Accept() >= 0)) {
    &do_request;
    # some error handle
}

$request->Finish();
exit 0;

~~~~~~~~
http://www.youtube.com/watch?v=VbUVqODL1nE