123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- /*
- * 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/>.
- */
- #ifndef __CONF_H___
- #define __CONF_H___
-
- #include <fcgiapp.h>
- #include <fcgi_stdio.h> /* fcgi library; put it first*/
-
- #define PY_SSIZE_T_CLEAN
- #include <Python.h>
- #include "structmember.h"
-
- #include <unistd.h>
- #include <getopt.h>
- #include <limits.h>
- #include <semaphore.h>
- #include <sys/types.h>
- #include <sys/wait.h>
-
- #include "config.h"
- /**@defgroup conf_internal PYFCGI configuration handling
- */
- /**@defgroup conf_glob PYFCGI global (for all process) configurations
- * @see struct_pyfcgi_conf_s
- * @ingroup conf_internal */
-
- /**@brief Friendly name for @ref struct pyfcgi_conf_s
- * @see struct pyfcgi_conf_s */
- typedef struct pyfcgi_conf_s pyfcgi_conf_t;
- typedef struct pyfcgi_conf_logger_s pyfcgi_conf_logger_t;
- typedef struct pyfcgi_context_s pyfcgi_context_t;
- typedef struct pyfcgi_semdata_s pyfcgi_semdata_t;
-
- /**@brief Configuration globals, inherited from parent to childs
- * @ingroup conf_internal
- */
- pyfcgi_conf_t PyFCGI_conf;
-
- /* Include other PyFCGI stuff */
- #include "logger.h"
- #include "pyutils.h"
- #include "ipc.h"
- #include "monitor.h"
-
- /**@defgroup ret_status Function & process return status
- */
- /**@ingroup ret_status */
- #define EXIT_PYERR 4
- /**@ingroup ret_status */
- #define PYFCGI_TIMEOUT 8
- /**@ingroup ret_status */
- #define PYFCGI_ERR 16
- /**@ingroup ret_status */
- #define PYFCGI_WORKER_FAIL 32
- /**@ingroup ret_status */
- #define PYFCGI_MASTER_FAIL 64
- /**@ingroup ret_status */
- #define PYFCGI_FATAL 128
-
- #define PYFCGI_NAME "spawn-fcgi [OPTIONS] -- pyfcgi"
-
- #define PYFCGI_SHORT_OPT "Ce:E:Aw:W:m:ft:L:SPsvVh"
-
- #define PYFCGI_LONG_OPT { \
- {"config", required_argument, 0, 'C'},\
- {"pymodule", required_argument, 0, 'e'},\
- {"pyapp", required_argument, 0, 'E'},\
- {"alt-io", no_argument, 0, 'A'},\
- {"min-worker", required_argument, 0, 'w'},\
- {"max-worker", required_argument, 0, 'W'},\
- {"max-request", required_argument, 0, 'm'},\
- {"fast-spawn", no_argument, 0, 'f'},\
- {"timeout", required_argument, 0, 't'},\
- {"log", required_argument, 0, 'L'},\
- {"syslog", no_argument, 0, 'S'},\
- {"pid-file", required_argument, 0, 'P'},\
- {"socket-server", required_argument, 0, 's'},\
- {"verbose", no_argument, 0, 'v'},\
- {"version", no_argument, 0, 'V'},\
- {"help", no_argument, 0, 'h' },\
- {0, 0, 0, 0}\
- }
-
- #define PYFCGI_OPT_HELP {\
- {"Load options from configuration file", "CONFIG"},\
- {"Search application function in given python module", "MODULE_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},\
- {"Minimum worker in the pool", "INT"},\
- {"Maximum worker in the pool", "INT"},\
- {"Request count after wich the worker is restarted (if 0 never restart)", "INT"},\
- {"If not given there is at least 1s between 2 child creation, else childs may be spawned in small burst", NULL},\
- {"Request timeout (before worker restarts)", "SECONDS"},\
- {"Add a logfile using syntax : 'LOGFILE[;FILT][;FMT]'", "LOGGER_SPEC"},\
- {"Use syslog for logging", NULL},\
- {"Create a PID file", "FILENAME"},\
- {"Indicate a socket (for example 'udp://localhost:8765' ) to listen on, replying stats & status", "SOCKET"},\
- {"Send all loglines on stderr", NULL},\
- {"Print PyFCGI and Python version and exit", NULL},\
- {"Display this help and exit", NULL},\
- }
-
- #define PYFCGI_HELP_TEXT "\n\
- Logger specification format 'LOGFILE[;FILT][;FMT]' with :\n\
- \t- LOGFILE the log file name\n\
- \t- FILT a number (in decimal or hexadicimal 0xXX) indicating wich\n\
- \t facility/level to log\n\
- \t- FMT the logline format in a special markup format using fields between { }\n\
- \t supported fields are :\n\
- \t\t- {datetime} {datetime:SIZE} {datetime:SIZE:FMT} defines a format and a \n\
- \t\t constant length for a datetime field. Default : {datetime:25:%F %T%z}\n\
- \t\t- {level} the loglevel \n\
- \t\t- {facility} the log facility\n\
- \t\t- {pid} the process PID\n\
- \t\t- {ident} the defined ident (set by process)\n\
- \t\t- {msg} the log message (can only appear once)\n\
- You can escape { and } by using {{ and }} and all field names can by\n\
- abbreviated to one character.\n\n\
- Socket URL specification format : PROT://HOST[:PORT] with PROT on of \n\
- \t- tcp for tcp sockets and HOST a valid INET address\n\
- \t- udp for udp sockets and HOST a valid INET address\n\
- \t- unix for file sockets and HOST a valid path\n\
- "
-
- #define PYENTRY_DEFAULT_FUN "application"
-
- /**@brief Stores a semaphore name and pointer */
- struct pyfcgi_semdata_s {
- /**@brief Semaphore names. Set by master process */
- char name[NAME_MAX - 4];
- /**@brief Semaphore pointer. */
- sem_t *sem;
- };
-
-
- /**@brief Stores contextual informations about current process */
- struct pyfcgi_context_s {
-
- /**@brief Stores current process PID */
- pid_t pid;
- /**@brief Stores parent process PID */
- pid_t ppid;
-
- /**@brief Stores the watchdog timer */
- timer_t wd_timer;
- /**@brief Security timer sending a sigkill */
- timer_t wd_timerkill;
- /**@brief Watchdog delay */
- struct timespec wd_delay;
- /**@brief Watchdog sig restorer */
- struct sigaction wd_oldsig;
- /**@brief watchdog flag */
- short wd;
-
- /**@brief array of worker pids (pool handler context) */
- pid_t **wrk_pids;
- /**@brief workers count */
- unsigned int n_wrk;
-
- /**@brief Stores IPC flag used in init */
- pyfcgi_ipc_flag_t ipc_flag;
-
- /**@brief Stores python_path (not dupped by python) */
- wchar_t python_path[PATH_MAX];
- /**@brief Stores venv_path for python home (not dupped by python) */
- wchar_t venv_path[PATH_MAX];
- /**@brief Stores a part of the environ (containing wsgi.* keys) */
- PyObject *wsgi_dict;
- };
-
- /**@brief Structure containing configuration
- * @ingroup conf_internal
- * The structure is used for the global @ref pyfcgi_conf variable.
- * @see pyfcgi_conf_t
- */
- struct pyfcgi_conf_s
- {
- /** @brief Stores pidfile path */
- char *pidfile;
-
- /**@brief Entrypoint module name
- * @ingroup conf_glob */
- char *py_entrymod;
- /**@brief Entrypoint function name
- * @ingroup conf_glob */
- char *py_entryfun;
- /**@brief If 0 use stdout to communicate with webserver, else
- * PyFCGI will expect PEP333 compliant entrypoint */
- short pep333;
- /**@brief Minimum count worker in pool
- * @ingroup conf_glob */
- int min_wrk;
- /**@brief Maximum count workers in pool
- * @ingroup conf_glob */
- int max_wrk;
- /**@brief Maximum request before a worker restarts (0 for no restart)
- * @ingroup conf_glob */
- int max_reqs;
-
- //Pool handling conf
- /**@brief Idle timeout : starts GC workers after Xs idle */
- time_t worker_gc_timeout;
- /**@brief Fast spawn : if 1 spawn more childs faster
- *
- * When not activated there is at least 1s between 2 child creation,
- * else child are created in small burst ( ~2 childs burst)
- */
- short worker_fast_spawn;
-
-
- //watchdogs config
- /**@brief Worker timeout in seconds (if 0 no timeout)*/
- time_t worker_timeout;
- /**@brief Pool timeout in seconds (if 0 no timeout)*/
- time_t pool_timeout;
-
- // logger config
- /**@brief 0 is silent 1 means logs to stderr */
- short verbosity;
- /**@brief Logger configuration
- * @ingroupe conf_glob */
- pyfcgi_conf_logger_t logs;
-
- /**@brief Context informations */
- pyfcgi_context_t context;
-
- /**@brief Semaphores informations
- *
- * - sems[0] is the worker state indicator : when a worker is idle the
- * sem is incremented
- * - sems[1] is the request counter sem : when a request is handled
- * this sem is incremented
- * - sems[2] is the stats/status SHM semaphore
- */
- pyfcgi_semdata_t sems[PYFCGI_NSEM];
-
- /**@brief Stores a copy of the specified socket URL to listen to. */
- char *mon_socket;
- /**@brief If 1 force ipv4 */
- short ipv4;
- /**@brief If 1 force ipv6 */
- short ipv6;
- };
-
-
- /**@brief Print usage on FD 2 (stdout) */
- void usage();
-
- /**@brief Print pyfcgi & python version on given fd */
- void print_version(int);
-
- /**@brief Init conf with default values */
- void default_conf();
-
- /**@brief Parse arguments and store them in conf
- * @return 0 if no error */
- int parse_args(int argc, char *argv[]);
-
- int check_entrypoint_import();
-
- int parse_optlog(const char*);
-
- /**@brief Initialize the watchdog
- * @param void (*wd_sig_cleaner)(int) pointer on a signal handler (or NULL to
- * use @ref pyfcgi_default_sighandler
- * @param const struct timespec* delay a pointer on the watchdog timeout
- * @return 0 if no error else -1
- */
- int pyfcgi_wd_init(void (*wd_sig_cleaner)(int), const struct timespec *delay);
- int pyfcgi_wd_arm();
- int pyfcgi_wd_pause();
- int pyfcgi_wd_stop();
-
- /**@brief Watchdog default signal handler */
- void pyfcgi_wd_default_sighandler(int signum);
-
- /**@brief Return a string representing a status
- * @param int status
- * @return a char* that should be freed
- */
- char *status2str(int);
-
- #endif
|