123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /*
- * Copyright (C) 2019 Weber Yann
- *
- * This file is part of PyFCGI.
- *
- * PyFCGI is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * any later version.
- *
- * PyFCGI is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with PyFCGI. If not, see <http://www.gnu.org/licenses/>.
- */
- /**@defgroup worker_process Worker processes
- * @brief Processus handling python execution with @ref work() function
- *
- * This kind of process are @ref spawn() by a @ref work_master_proc
- * @section Running Python
- * Running embed python in FCGI mean serving multiple requests with a single
- * python process, meaning :
- * - environnement variable of the living Python process need to be updated
- * - we need a way to communicate with python code
- *
- * @subsection worker_proc_ipc Communicating with python
- * sys.stdout & sys.stderr will be used to communicate in python. Shortly
- * after python initialize @ref update_python_fd() update these two file
- * objects with freshly created pipes.
- *
- * @subsubsection worker_proc_ipc_piper The piper process
- *
- * When a request arrive, the worker process fork again in a @ref worker_piper() child
- * process that will read the two pipes. Sending stdout to FCGI using printf
- * and stderr to syslog.
- *
- * @subsection worker_proc_environ Updating os.environ
- * os.environ is a special kind of dictionnary, automatically calling
- * os.putenv() function. This function will attempt (and succeed) to update
- * the real process environnement, making a nasty conflict with libfcgi (trying
- * to free an environnement it did not create anymore...).
- *
- * The os.environ is replaced by a simple python dict by @ref update_pyenv()
- * once a request.
- *
- * @see update_python_path()
- *
- * @ingroup processes
- * @ingroup work_master_proc
- */
- /**@file pyworker.h
- * @ingroup worker_process
- */
- #ifndef _PYWORKER__H___
- #define _PYWORKER__H___
-
- #include "config.h"
-
- #include <fcgiapp.h>
- #include <fcgi_stdio.h> /* fcgi library; put it first*/
-
- #define PY_SSIZE_T_CLEAN
- #include <Python.h>
-
-
- #include <unistd.h>
- #include <fcntl.h>
- #include <syslog.h>
- #include <signal.h>
- #include <limits.h>
- #include <poll.h>
- #include <sched.h>
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <sys/wait.h>
-
- #include "logger.h"
- #include "pyutils.h"
- #include "python_pyfcgi.h"
-
- #define WPIPER_SIG 30
- #define PIPER_STACK_SZ (1024 * 1024 * 4)
-
- //extern char **environ;
-
- typedef unsigned long int pywrkid_t;
- typedef struct piper_args_s piper_args_t;
-
- struct piper_args_s
- {
- int wrk_id, pystdout, pystderr, ctl_pipe;
- //int req_id;
- FCGX_Stream *out;
- struct sigaction *act;
- };
-
- extern PyObject* response_status;
- extern PyObject* response_headers;
-
- /**@brief The function that initialize the alternate python worker
- * @ingroup worker_process
- *
- * This function handles python worker by running a PEP333 application function.
- * The start_response() function set @ref response_status and
- * @ref response_headers globals.
- * @param char* python_entrypoint a path to a python entrypoint
- * @param int worker uid
- * @return 0 if exit avec max requests
- */
- int work333(int);
-
- /**@brief the function that initialize the alternate python worker
- * @ingroup worker_process
- *
- * This function handles python worker using stdout to communicate with
- * FCGI. This function clones for each request, running worker_piper()
- * @param char* python_entrypoint a path to a python entrypoint
- * @param int worker uid
- * @return 0 if exit avec max requests
- */
- int work(int);
-
- /**@brief function for a subprocess designed to read stdin & stdout from
- * python & forward them to syslog or FCGI
- * @ingroup worker_process
- * @param int worker id
- * @param int request id
- * @param int pystdout
- * @param int pystderr
- * @param int ctlpipe a pipe closed when the process is ready
- * @note Exit after signal sent by parent & when poll indicate the pipes are
- * empty
- */
- /*
- void worker_piper(int, int, int, int, int, FCGX_Stream*);
- */
- int worker_piper(void*);
-
- /**@brief worker piper sigaction handler
- */
- void worker_piper_sighandler(int);
-
- /**@brief empty pipes and log content for pep333 workers
- * @todo enhance logging : 1 lines per logline + line counter ?
- * @todo sys.stdout & sys.stderr can have an implementation like
- * libpyfcgi.IoIn to avoir useless buffering
- * @param int pipes for stdout
- * @param int pipes for stderr
- * @param PyObject[2] python flush methods
- */
- void worker_log_pipes(int, int, PyObject*[2]);
-
- /**@brief Attempt to read the request size from ctl pipe
- * @param int ctl pipe read fd
- * @param size_t* rep_sz
- * @return 0 if no error
- */
- int ctl_get_rep_sz(int, size_t*);
-
- void worker_sighandler(int);
- void worker_sigalrmhandler(int signum);
-
- #endif
|