PyFCGI now handles fcgi socket creation
Add a -l --listen option to set the socket path or address:port Fix a bug using thread safe functions from libfcgi
This commit is contained in:
parent
d1eaf6979f
commit
f685f83369
7 changed files with 70 additions and 11 deletions
6
README
6
README
|
|
@ -9,10 +9,10 @@ Building & running pyfcgi :
|
||||||
$ ./configure
|
$ ./configure
|
||||||
$ make
|
$ make
|
||||||
# To run foo_pep333.entrypoint() PEP333 application
|
# To run foo_pep333.entrypoint() PEP333 application
|
||||||
$ spawn-fcgi -d . -n -p 9000 -a 127.0.0.1 -- src/pyfcgi -S -e foo_pep333 -E entrypoint
|
$ src/pyfcgi -l '127.0.0.1:9000' -S -e foo_pep333 -E entrypoint
|
||||||
or
|
or
|
||||||
# To run foo.entrypoint() sending to FCGI python stdout
|
# To run foo.entrypoint() sending to FCGI python stdout
|
||||||
$ spawn-fcgi -d . -n -p 9000 -a 127.0.0.1 -- src/pyfcgi -S -e foo -E entrypoint -A
|
$ src/pyfcgi -l '127.0.0.1:9000' -S -e foo -E entrypoint -A
|
||||||
|
|
||||||
|
|
||||||
configure script determine python flags, libs & includes paths using
|
configure script determine python flags, libs & includes paths using
|
||||||
|
|
@ -23,7 +23,7 @@ Example : linking against a debug build of python :
|
||||||
---------
|
---------
|
||||||
$ ./configure PYTHON_CONFIG_PATH=/usr/bin/python3dm-config --enable-debug
|
$ ./configure PYTHON_CONFIG_PATH=/usr/bin/python3dm-config --enable-debug
|
||||||
$ make clean && make
|
$ make clean && make
|
||||||
$ valgrind --log-file=/tmp/val.log --trace-children=yes spawn-fcgi -d . -n -p 9000 -a 127.0.0.1 -- src/pyfcgi -S -e foo_pep333 -E entrypoint -L '/tmp/foo.log;0xff;{datetime} {msg} {ident}'
|
$ valgrind --log-file=/tmp/val.log --trace-children=yes src/pyfcgi -S -e foo_pep333 -E entrypoint -L '/tmp/foo.log;0xff;{datetime} {msg} {ident}'
|
||||||
|
|
||||||
logging to file example :
|
logging to file example :
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.TH "pyfcgi" 1 "Sat Aug 24 2019" "Version 0.0.1" "PyFCGI" \" -*- nroff -*-
|
.TH "pyfcgi" 1 "Mon Oct 28 2019" "Version 0.0.1" "PyFCGI" \" -*- nroff -*-
|
||||||
.ad l
|
.ad l
|
||||||
.nh
|
.nh
|
||||||
.SH NAME
|
.SH NAME
|
||||||
|
|
@ -24,11 +24,16 @@ Display help and exit
|
||||||
Display pyfcgi and Python version and exit
|
Display pyfcgi and Python version and exit
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
\fB-c --config=FILE\fP
|
\fB-C --config=FILE\fP
|
||||||
.RS 4
|
.RS 4
|
||||||
load a configuration file
|
load a configuration file
|
||||||
.RE
|
.RE
|
||||||
.PP
|
.PP
|
||||||
|
\fB-l --listen=SOCK_PATH\fP
|
||||||
|
.RS 4
|
||||||
|
fcgi listen socket path\&. For TCP socket use 'IPv4:PORT' syntax ( '127\&.0\&.0\&.1:9000' by default)
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
\fB-e --pymodule=MODULE_NAME\fP
|
\fB-e --pymodule=MODULE_NAME\fP
|
||||||
.RS 4
|
.RS 4
|
||||||
python entrypoint module name
|
python entrypoint module name
|
||||||
|
|
@ -134,11 +139,11 @@ unix with HOST a valid PATH
|
||||||
.PP
|
.PP
|
||||||
To run foo_pep333\&.entrypoint() PEP333 application :
|
To run foo_pep333\&.entrypoint() PEP333 application :
|
||||||
.PP
|
.PP
|
||||||
spawn-fcgi -d \&. -n -p 9000 -a 127\&.0\&.0\&.1 -- src/pyfcgi -S \\ -e foo_pep333 -E entrypoint
|
spawn-fcgi -d \&. -n -p 9000 -a 127\&.0\&.0\&.1 -- src/pyfcgi -S -e foo_pep333 -E entrypoint
|
||||||
.PP
|
.PP
|
||||||
Logfile example :
|
Logfile example :
|
||||||
.PP
|
.PP
|
||||||
spawn-fcgi -d \&. -n -p 9000 -a 127\&.0\&.0\&.1 -- src/pyfcgi -S \\ -e foo_pep333 -E entrypoint \\ -L '/tmp/foo\&.log;0xff;{datetime} {msg} {ident}'
|
spawn-fcgi -d \&. -n -p 9000 -a 127\&.0\&.0\&.1 -- src/pyfcgi -S -e foo_pep333 -E entrypoint -L '/tmp/foo\&.log;0xff;{datetime} {msg} {ident}'
|
||||||
.SH "AUTHOR"
|
.SH "AUTHOR"
|
||||||
.PP
|
.PP
|
||||||
Written by Yann Weber <yann.weber@member.fsf.org>
|
Written by Yann Weber <yann.weber@member.fsf.org>
|
||||||
|
|
|
||||||
|
|
@ -74,12 +74,16 @@ pyfcgi_conf_t PyFCGI_conf;
|
||||||
/**@ingroup ret_status */
|
/**@ingroup ret_status */
|
||||||
#define PYFCGI_FATAL 128
|
#define PYFCGI_FATAL 128
|
||||||
|
|
||||||
|
/**@brief Backlog argument for socket creation */
|
||||||
|
#define PYFCGI_SOCK_BACKLOG 100
|
||||||
|
|
||||||
#define PYFCGI_NAME "spawn-fcgi [OPTIONS] -- pyfcgi"
|
#define PYFCGI_NAME "spawn-fcgi [OPTIONS] -- pyfcgi"
|
||||||
|
|
||||||
#define PYFCGI_SHORT_OPT "Ce:E:Aw:W:m:ft:L:SPs:vVh"
|
#define PYFCGI_SHORT_OPT "C:l:e:E:Aw:W:m:ft:L:SPs:vVh"
|
||||||
|
|
||||||
#define PYFCGI_LONG_OPT { \
|
#define PYFCGI_LONG_OPT { \
|
||||||
{"config", required_argument, 0, 'C'},\
|
{"config", required_argument, 0, 'C'},\
|
||||||
|
{"listen", required_argument, 0, 'l'},\
|
||||||
{"pymodule", required_argument, 0, 'e'},\
|
{"pymodule", required_argument, 0, 'e'},\
|
||||||
{"pyapp", required_argument, 0, 'E'},\
|
{"pyapp", required_argument, 0, 'E'},\
|
||||||
{"alt-io", no_argument, 0, 'A'},\
|
{"alt-io", no_argument, 0, 'A'},\
|
||||||
|
|
@ -100,6 +104,7 @@ pyfcgi_conf_t PyFCGI_conf;
|
||||||
|
|
||||||
#define PYFCGI_OPT_HELP {\
|
#define PYFCGI_OPT_HELP {\
|
||||||
{"Load options from configuration file", "CONFIG"},\
|
{"Load options from configuration file", "CONFIG"},\
|
||||||
|
{"Listen socket path (a path for UNIX socket or a 'IPV4:PORT' string)", "SOCK_PATH"},\
|
||||||
{"Search application function in given python module", "MODULE_NAME"},\
|
{"Search application function in given python module", "MODULE_NAME"},\
|
||||||
{"Python application entrypoint function name", "FUNC_NAME"},\
|
{"Python application entrypoint function name", "FUNC_NAME"},\
|
||||||
{"Use stdout to communicate with web server instead of entrypoint return as specified in PEP 333", NULL},\
|
{"Use stdout to communicate with web server instead of entrypoint return as specified in PEP 333", NULL},\
|
||||||
|
|
@ -176,6 +181,12 @@ struct pyfcgi_context_s {
|
||||||
/**@brief Stores parent process PID */
|
/**@brief Stores parent process PID */
|
||||||
pid_t ppid;
|
pid_t ppid;
|
||||||
|
|
||||||
|
/**@brief Returned by FCGX_OpenSocket for responder process */
|
||||||
|
int fcgi_socket;
|
||||||
|
|
||||||
|
/**@brief Request information (local to each worker) */
|
||||||
|
FCGX_Request fcgi_request;
|
||||||
|
|
||||||
/**@brief Stores the watchdog timer */
|
/**@brief Stores the watchdog timer */
|
||||||
timer_t wd_timer;
|
timer_t wd_timer;
|
||||||
/**@brief Security timer sending a sigkill */
|
/**@brief Security timer sending a sigkill */
|
||||||
|
|
@ -215,6 +226,10 @@ struct pyfcgi_conf_s
|
||||||
/** @brief Stores pidfile path */
|
/** @brief Stores pidfile path */
|
||||||
char *pidfile;
|
char *pidfile;
|
||||||
|
|
||||||
|
/**@brief Stores the socket path argument
|
||||||
|
* @ingroup conf_glob
|
||||||
|
* Can be a file path for a UNIX socket or IPv4:PORT string */
|
||||||
|
char *sock_path;
|
||||||
/**@brief Entrypoint module name
|
/**@brief Entrypoint module name
|
||||||
* @ingroup conf_glob */
|
* @ingroup conf_glob */
|
||||||
char *py_entrymod;
|
char *py_entrymod;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ void print_version(int fd)
|
||||||
void default_conf()
|
void default_conf()
|
||||||
{
|
{
|
||||||
memset(&PyFCGI_conf, 0, sizeof(pyfcgi_conf_t));
|
memset(&PyFCGI_conf, 0, sizeof(pyfcgi_conf_t));
|
||||||
|
PyFCGI_conf.sock_path = "127.0.0.1:9000";
|
||||||
PyFCGI_conf.context.pid = getpid();
|
PyFCGI_conf.context.pid = getpid();
|
||||||
PyFCGI_conf.min_wrk = 1;
|
PyFCGI_conf.min_wrk = 1;
|
||||||
PyFCGI_conf.max_wrk = 5;
|
PyFCGI_conf.max_wrk = 5;
|
||||||
|
|
@ -72,6 +73,9 @@ int parse_args(int argc, char *argv[])
|
||||||
case 'C':
|
case 'C':
|
||||||
dprintf(2, "Config parser not yet implemented :'(\n");
|
dprintf(2, "Config parser not yet implemented :'(\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
case 'l':
|
||||||
|
PyFCGI_conf.sock_path = strdup(optarg);
|
||||||
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
PyFCGI_conf.py_entrymod = strdup(optarg);
|
PyFCGI_conf.py_entrymod = strdup(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -362,8 +362,11 @@ if ($programname contains 'pyfcgi') then {
|
||||||
* Display help and exit
|
* Display help and exit
|
||||||
* @par -V --version
|
* @par -V --version
|
||||||
* Display pyfcgi and Python version and exit
|
* Display pyfcgi and Python version and exit
|
||||||
* @par -c --config=FILE
|
* @par -C --config=FILE
|
||||||
* load a configuration file
|
* load a configuration file
|
||||||
|
* @par -l --listen=SOCK_PATH
|
||||||
|
* fcgi listen socket path. For TCP socket use "IPv4:PORT" syntax (
|
||||||
|
* "127.0.0.1:9000" by default)
|
||||||
* @par -e --pymodule=MODULE_NAME
|
* @par -e --pymodule=MODULE_NAME
|
||||||
* python entrypoint module name
|
* python entrypoint module name
|
||||||
* @par -E --pyapp=FUNC_NAME
|
* @par -E --pyapp=FUNC_NAME
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ int work333(int wrk_id)
|
||||||
int count, pipe_out[2], pipe_err[2];
|
int count, pipe_out[2], pipe_err[2];
|
||||||
int max_reqs;
|
int max_reqs;
|
||||||
struct timeval start, stop;
|
struct timeval start, stop;
|
||||||
|
FCGX_Request *request;
|
||||||
|
|
||||||
max_reqs = PyFCGI_conf.max_reqs;
|
max_reqs = PyFCGI_conf.max_reqs;
|
||||||
|
|
||||||
|
|
@ -72,13 +73,28 @@ int work333(int wrk_id)
|
||||||
|
|
||||||
start_response = get_start_response();
|
start_response = get_start_response();
|
||||||
|
|
||||||
|
// Initialise FCGI request
|
||||||
|
request = &(PyFCGI_conf.context.fcgi_request);
|
||||||
|
if(FCGX_InitRequest(request, PyFCGI_conf.context.fcgi_socket,
|
||||||
|
FCGI_FAIL_ACCEPT_ON_INTR) == -1)
|
||||||
|
{
|
||||||
|
pyfcgi_log(LOG_ALERT, "Unable to init FCGI request");
|
||||||
|
exit(PYFCGI_FATAL);
|
||||||
|
}
|
||||||
|
|
||||||
_worker_idle = 0;
|
_worker_idle = 0;
|
||||||
worker_set_idle();
|
worker_set_idle();
|
||||||
// requests accepting loop
|
// requests accepting loop
|
||||||
count = 0;
|
count = 0;
|
||||||
while ((!count || count != max_reqs) &&
|
while ((!count || count != max_reqs) &&
|
||||||
FCGX_Accept(&in_stream, &out_stream, &err_stream, &envp) >= 0)
|
FCGX_Accept_r(request) == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
in_stream = request->in;
|
||||||
|
out_stream = request->out;
|
||||||
|
err_stream = request->err;
|
||||||
|
envp = request->envp;
|
||||||
|
|
||||||
pyfcgi_wd_arm();
|
pyfcgi_wd_arm();
|
||||||
sem_post(PyFCGI_SEM(SEM_WREQS).sem); // increment request counter discarding OF
|
sem_post(PyFCGI_SEM(SEM_WREQS).sem); // increment request counter discarding OF
|
||||||
gettimeofday(&start, NULL);
|
gettimeofday(&start, NULL);
|
||||||
|
|
@ -136,7 +152,7 @@ int work333(int wrk_id)
|
||||||
FCGX_FClose(out_stream);
|
FCGX_FClose(out_stream);
|
||||||
FCGX_FClose(in_stream);
|
FCGX_FClose(in_stream);
|
||||||
FCGX_FClose(err_stream);
|
FCGX_FClose(err_stream);
|
||||||
FCGI_Finish();
|
FCGX_Finish_r(request);
|
||||||
|
|
||||||
gettimeofday(&stop, NULL);
|
gettimeofday(&stop, NULL);
|
||||||
stop.tv_sec = stop.tv_sec - start.tv_sec;
|
stop.tv_sec = stop.tv_sec - start.tv_sec;
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,22 @@ void init_context()
|
||||||
}
|
}
|
||||||
bzero(PyFCGI_conf.context.wrk_pids,
|
bzero(PyFCGI_conf.context.wrk_pids,
|
||||||
sizeof(pid_t) * (PyFCGI_conf.max_wrk + 1));
|
sizeof(pid_t) * (PyFCGI_conf.max_wrk + 1));
|
||||||
|
|
||||||
|
// Open FCGI listen socket
|
||||||
|
PyFCGI_conf.context.fcgi_socket = FCGX_OpenSocket(PyFCGI_conf.sock_path,
|
||||||
|
PYFCGI_SOCK_BACKLOG);
|
||||||
|
if(PyFCGI_conf.context.fcgi_socket == -1)
|
||||||
|
{
|
||||||
|
pyfcgi_log(LOG_ALERT, "Unable to open socket : '%s'",
|
||||||
|
PyFCGI_conf.sock_path);
|
||||||
|
clean_exit(PYFCGI_FATAL);
|
||||||
|
}
|
||||||
|
if(FCGX_Init() != 0)
|
||||||
|
{
|
||||||
|
pyfcgi_log(LOG_ALERT, "Unable to init libfcgi");
|
||||||
|
clean_exit(PYFCGI_FATAL);
|
||||||
|
}
|
||||||
|
pyfcgi_log(LOG_INFO, "Listening on %s", PyFCGI_conf.sock_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int responder_loop()
|
int responder_loop()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue