Tests about a simple python3 fastcgi runner using libfcgi and the Python-C API.
python
c
wsgi
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pyworker.h 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (C) 2019 Weber Yann
  3. *
  4. * This file is part of PyFCGI.
  5. *
  6. * PyFCGI is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * any later version.
  10. *
  11. * PyFCGI is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with PyFCGI. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /**@defgroup worker_process Worker processes
  20. * @brief Processus handling python execution with @ref work() function
  21. *
  22. * This kind of process are @ref spawn() by a @ref work_master_proc
  23. * @section Running Python
  24. * Running embed python in FCGI mean serving multiple requests with a single
  25. * python process, meaning :
  26. * - environnement variable of the living Python process need to be updated
  27. * - we need a way to communicate with python code
  28. *
  29. * @subsection worker_proc_ipc Communicating with python
  30. * sys.stdout & sys.stderr will be used to communicate in python. Shortly
  31. * after python initialize @ref update_python_fd() update these two file
  32. * objects with freshly created pipes.
  33. *
  34. * @subsubsection worker_proc_ipc_piper The piper process
  35. *
  36. * When a request arrive, the worker process fork again in a @ref worker_piper() child
  37. * process that will read the two pipes. Sending stdout to FCGI using printf
  38. * and stderr to syslog.
  39. *
  40. * @subsection worker_proc_environ Updating os.environ
  41. * os.environ is a special kind of dictionnary, automatically calling
  42. * os.putenv() function. This function will attempt (and succeed) to update
  43. * the real process environnement, making a nasty conflict with libfcgi (trying
  44. * to free an environnement it did not create anymore...).
  45. *
  46. * The os.environ is replaced by a simple python dict by @ref update_pyenv()
  47. * once a request.
  48. *
  49. * @see update_python_path()
  50. *
  51. * @ingroup processes
  52. * @ingroup work_master_proc
  53. */
  54. /**@file pyworker.h
  55. * @ingroup worker_process
  56. */
  57. #ifndef _PYWORKER__H___
  58. #define _PYWORKER__H___
  59. #include "config.h"
  60. #include <fcgiapp.h>
  61. #include <fcgi_stdio.h> /* fcgi library; put it first*/
  62. #define PY_SSIZE_T_CLEAN
  63. #include <Python.h>
  64. #include <unistd.h>
  65. #include <fcntl.h>
  66. #include <syslog.h>
  67. #include <signal.h>
  68. #include <limits.h>
  69. #include <poll.h>
  70. #include <sched.h>
  71. #include <sys/types.h>
  72. #include <sys/ipc.h>
  73. #include <sys/sem.h>
  74. #include <sys/wait.h>
  75. #include "logger.h"
  76. #include "pyutils.h"
  77. #include "python_pyfcgi.h"
  78. #define WPIPER_SIG 30
  79. #define PIPER_STACK_SZ (1024 * 1024 * 4)
  80. //extern char **environ;
  81. typedef unsigned long int pywrkid_t;
  82. typedef struct piper_args_s piper_args_t;
  83. struct piper_args_s
  84. {
  85. int wrk_id, pystdout, pystderr, ctl_pipe;
  86. //int req_id;
  87. FCGX_Stream *out;
  88. struct sigaction *act;
  89. };
  90. extern PyObject* response_status;
  91. extern PyObject* response_headers;
  92. /**@todo TODO on all request (when updating env ?) update stdin so
  93. * python will be able to read the request content */
  94. /**@brief The function that initialize the alternate python worker
  95. * @ingroup worker_process
  96. *
  97. * This function handles python worker by running a PEP333 application function.
  98. * The start_response() function set @ref response_status and
  99. * @ref response_headers globals.
  100. * @param char* python_entrypoint a path to a python entrypoint
  101. * @param int worker uid
  102. * @param int semid for FCGI access
  103. * @return 0 if exit avec max requests
  104. */
  105. int work333(int, int);
  106. /**@brief the function that initialize the alternate python worker
  107. * @ingroup worker_process
  108. *
  109. * This function handles python worker using stdout to communicate with
  110. * FCGI. This function clones for each request, running worker_piper()
  111. * @param char* python_entrypoint a path to a python entrypoint
  112. * @param int worker uid
  113. * @param int semid for FCGI access
  114. * @return 0 if exit avec max requests
  115. */
  116. int work(int, int);
  117. /**@brief function for a subprocess designed to read stdin & stdout from
  118. * python & forward them to syslog or FCGI
  119. * @ingroup worker_process
  120. * @param int worker id
  121. * @param int request id
  122. * @param int pystdout
  123. * @param int pystderr
  124. * @param int ctlpipe a pipe closed when the process is ready
  125. * @note Exit after signal sent by parent & when poll indicate the pipes are
  126. * empty
  127. */
  128. /*
  129. void worker_piper(int, int, int, int, int, FCGX_Stream*);
  130. */
  131. int worker_piper(void*);
  132. /**@brief worker piper sigaction handler
  133. */
  134. void worker_piper_sighandler(int);
  135. /**@brief Attempt to read the request size from ctl pipe
  136. * @param int ctl pipe read fd
  137. * @param size_t* rep_sz
  138. * @return 0 if no error
  139. */
  140. int ctl_get_rep_sz(int, size_t*);
  141. #endif