/*
* 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 .
*/
/**@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
#include /* fcgi library; put it first*/
#define PY_SSIZE_T_CLEAN
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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