gnosek / fcgiwrap

Simple FastCGI wrapper for CGI scripts
http://nginx.localdomain.pl/
MIT License
407 stars 134 forks source link

Child process not detached #40

Open cescp opened 7 years ago

cescp commented 7 years ago

I'm trying to do the following: when a request is received, an immediate response 202 should be given, while a long background process is started. In nginx.conf:

    location /do-something {
        fastcgi_pass  unix:/var/run/fcgiwrap.socket;
        # Fastcgi parameters, include the standard ones
        include /etc/nginx/fastcgi_params;
        # Adjust non standard parameters (SCRIPT_FILENAME)
        fastcgi_param SCRIPT_FILENAME /usr/local/bin/do-something.sh;
    }

/usr/local/bin/do-something.sh

#!/bin/bash
echo "Status: 202"
echo -e "Content-type: text/plain\n"

echo "Calling child process..."
/usr/local/bin/do-process.sh &
echo "Returned from child process."

exit 0

/usr/local/bin/do-process.sh

#!/bin/bash

echo "Starting child process..."
sleep 10
echo "Child process done."

exit 0

The expected result is that ampersand used in calling do-process.sh should detach the child process, and 202 code should be returned immediately, as when calling /usr/local/bin/do-something.sh from console. But when I make a request via nginx:

curl -i http://127.0.0.1/do-something

the response is not given immediately, but after 10 seconds.

I'm using spawn with config /etc/sysconfig/spawn-fcgi:

FCGI_SOCKET=/var/run/fcgiwrap.socket
FCGI_PROGRAM=/usr/local/sbin/fcgiwrap
FCGI_USER=nginx
FCGI_GROUP=nginx
FCGI_EXTRA_OPTIONS="-M 0770"
OPTIONS="-u $FCGI_USER -g $FCGI_GROUP -s $FCGI_SOCKET -S $FCGI_EXTRA_OPTIONS -F 1 -P /var/run/spawn-fcgi.pid -- $FCGI_PROGRAM"

in a CentOS 7 computer.

Is this the right way of calling a process and start a child process without waiting it to finish?

gnosek commented 7 years ago

Off the top of my head, try closing stdin, stdout and stderr in the child process, probably something like:

exec 0<&-
exec 1>&-
exec 2>&-

Of course this means you won't be able to produce any more content from the background script but you don't really have a place to send it to anyway (you might get away with closing stdout only and keep logging to stderr but you'd have to check it)

cescp commented 7 years ago

Your solution worked! As you suggested:

#!/bin/bash
exec 0<&-
exec 1>&-
exec 2>&-
echo "Starting child process..."
sleep 10
echo "Child process done."

exit 0

makes the child to be detached. Specifying redirection in do-something.sh, instead of do-process.sh, also worked:

#!/bin/bash
echo "Status: 202"
echo -e "Content-type: text/plain\n"

echo "Calling child process..."
/usr/local/bin/do-process.sh 1>&- 2>&- &
echo "Returned from child process."

exit 0

You can even specify a file where to redirect the stdout or stderr of the child:

/usr/local/bin/do-process.sh 1>&- 2>/tmp/stderr_from_do-process &

but you must always specify a redirection for 1 and for 2. If one of the two redirections is missing, the child process is not detached. Thank you very much!

aknrdureegaesr commented 5 years ago

@cescp : Is there any reason why this issue is still open? What do you expect that fcgiwrap project to do about it? - If nothing, kindly close.