Browse Source

Commenting, adding Doxyfile, enhancing Makefile

Yann Weber 4 years ago
parent
commit
ebb01bb82e
6 changed files with 2656 additions and 10 deletions
  1. 2494
    0
      Doxyfile
  2. 13
    3
      Makefile
  3. 8
    4
      src/Makefile
  4. 73
    1
      src/main.c
  5. 42
    0
      src/pyworker.h
  6. 26
    2
      src/responder.h

+ 2494
- 0
Doxyfile
File diff suppressed because it is too large
View File


+ 13
- 3
Makefile View File

@@ -1,7 +1,17 @@
1 1
 all:
2 2
 	+make -C src
3 3
 
4
-.PHONY: clean
4
+doc: 
5
+	doxygen
5 6
 
6
-clean:
7
-	make -C src clean
7
+.PHONY: distclean clean __pycache__clean doc
8
+
9
+distclean: __pycache__clean
10
+	-make -C src distclean;\
11
+	rm -Rvf doc/latex doc/html doc/man
12
+
13
+clean: __pycache__clean
14
+	-make -C src clean;\
15
+
16
+__pycache__clean:
17
+	rm -Rvf __pycache__

+ 8
- 4
src/Makefile View File

@@ -4,18 +4,22 @@ CFLAGS=-c -Wall `python3-config --includes`
4 4
 LDFLAGS=`python3-config --libs` -lfcgi
5 5
 #LDFLAGS= -L`python3-config --configdir` `python3-config --libs` -lfcgi
6 6
 
7
+BIN=pyfcgi
7 8
 SRCS=$(wildcard *.c)
8 9
 OBJS=$(SRCS:.c=.o)
9 10
 
10
-all: pyfcgi
11
+all: $(BIN)
11 12
 
12
-pyfcgi: $(OBJS)
13
+$(BIN): $(OBJS)
13 14
 	$(CC) $(LDFLAGS) -o $@ $^
14 15
 
15 16
 %.o: %.c
16 17
 	$(CC) $(CFLAGS) -o $@ $<
17 18
 
18
-.PHONY: clean
19
+.PHONY: clean distclean
20
+
21
+distclean: clean
22
+	-rm -v $(BIN)
19 23
 
20 24
 clean:
21
-	@rm -v $(OBJS)
25
+	-rm -v $(OBJS)

+ 73
- 1
src/main.c View File

@@ -16,6 +16,19 @@
16 16
  * You should have received a copy of the GNU Affero General Public License
17 17
  * along with PyFCGI.  If not, see <http://www.gnu.org/licenses/>.
18 18
  */
19
+
20
+/**@defgroup processes Process organisation of PyFCGI
21
+ *
22
+ * PyFCGI is organised in three layer : 
23
+ * A @ref main_proc : simple, that keep running and spawn a
24
+ * @ref work_master_proc . This process handles @ref worker_process creation
25
+ * and try to maintain a pool able to reply efficiently to CGI requests.
26
+ */
27
+/**@defgroup main_proc Main process
28
+ * @brief The main process in the @ref main() function
29
+ * @ingroup processes
30
+ */
31
+
19 32
 #include <fcgi_stdio.h> /* fcgi library; put it first*/
20 33
 
21 34
 #include <unistd.h>
@@ -76,7 +89,7 @@ int main(int argc, char **argv)
76 89
 		}
77 90
 		else if(!child)
78 91
 		{
79
-			responder_loop(py_entrypoint, MAX_REQS, 1, 20);
92
+			responder_loop(py_entrypoint, MAX_REQS, 1, 30);
80 93
 			exit((unsigned char)-1);
81 94
 		}
82 95
 		waitpid(child, &child_ret, 0);
@@ -94,3 +107,62 @@ int main(int argc, char **argv)
94 107
 	closelog();
95 108
 	free(ident);
96 109
 }
110
+
111
+/**@mainpage PyFCGI
112
+ * @section main_what What is PyFCGI ?
113
+ * PyFCGI is a simple python3 fastcgi runner.
114
+ *
115
+ * Usage : *PY_ENTRYPOINT='foo' spawn-fcgi -d . -n src/pyfcgi -p 9000 -a 127.0.0.1*
116
+ *
117
+ * To run foo.entrypoint() python function.
118
+ *
119
+ * @subsection main_how_use How to use it ?
120
+ * 
121
+ * @warning For the moment PyFCGI is under heavy developpement and in early
122
+ * stage. Everything will change ;o)
123
+ *
124
+ * PyFCGI should be runned with spawn-fcgi (or something similar), allowing
125
+ * to configure & forward environnement variables to libFCGI.
126
+ *
127
+ * For the moment no configuration files exists. You have to pass a 
128
+ * PY_ENTRYPOINT containing an importable python module containing an
129
+ * entrypoint() (no arguments for the moment) function.
130
+ *
131
+ * When called this function will have to send valid CGI data to the webserver
132
+ * using sys.stdin (the print() function for exemple) like :
133
+ *<code>Content-type: text/html\\r\\n\\r\\nHello world !\\n</code>
134
+ *
135
+ * The function will have access to updated CGI os.environ containing
136
+ * all informations about a request
137
+ *
138
+ * @subsubsection main_how_use_syslog Logging, using syslog
139
+ * 
140
+ * Right now PyFCGI uses syslog() to log stuff using a pyfcgi ident.
141
+ * PyFCGI logs can be filtered using /etc/rsyslog.d/pyfcgi.conf :
142
+ * 
143
+<pre>
144
+if ($programname contains 'pyfcgi') then {
145
+	-/var/log/pyfcgi/pyfcgi.log
146
+	stop
147
+}
148
+</pre>
149
+ *
150
+ * @subsubsection main_how_use_hardcode Hardcoded stuffs
151
+ *
152
+ * Right now there is a lot of hardcodd stuff. Fortunatly a vast majority
153
+ * is in @ref main.c like the minimum and maximum number of workers, or
154
+ * the number of requests before a worker restart. Some timers and stuff
155
+ * are harcoded but should not in @ref pyworker.c & @ref responder.c
156
+ *
157
+ * @subsection main_how_works How it works ?
158
+ *
159
+ * - @ref processes
160
+ *  - @ref main_proc
161
+ *  - @ref work_master_proc
162
+ *  - @ref worker_process
163
+ *
164
+ * @subsection main_how_todo TODO
165
+ * @todo Add another logging facility
166
+ * @todo Add a configuration mecanism
167
+ */
168
+

+ 42
- 0
src/pyworker.h View File

@@ -16,6 +16,44 @@
16 16
  * You should have received a copy of the GNU Affero General Public License
17 17
  * along with PyFCGI.  If not, see <http://www.gnu.org/licenses/>.
18 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
+ */
19 57
 #ifndef _PYWORKER__H___
20 58
 #define _PYWORKER__H___
21 59
 
@@ -48,6 +86,7 @@ typedef unsigned long int pywrkid_t;
48 86
 
49 87
 
50 88
 /**@brief the function that initialize the python worker
89
+ * @ingroup worker_process
51 90
  * @param char* python_entrypoint a path to a python entrypoint
52 91
  * @param int worker uid
53 92
  * @param int semid for FCGI access
@@ -58,6 +97,7 @@ int work(char*, int, int, int);
58 97
 
59 98
 /**@brief function for a subprocess designed to read stdin & stdout from
60 99
  * python & forward them to syslog or FCGI
100
+ * @ingroup worker_process
61 101
  * @param int worker id
62 102
  * @param int request id
63 103
  * @param int pystdout
@@ -87,12 +127,14 @@ void fetch_pyflush(PyObject**, PyObject**);
87 127
 void update_python_path();
88 128
 
89 129
 /**@brief Create two pipes for stdout & stderr
130
+ * @ingroup worker_process
90 131
  * @params int[2] pystdout
91 132
  * @params int[2] pystderr
92 133
  */
93 134
 void update_python_fd(int[2], int[2]);
94 135
 
95 136
 /**@brief Clear then update python sys.environ using current FCI environ
137
+ * @ingroup worker_process
96 138
  * @note The environ has to be set without a call to os.putenv, the problem
97 139
  * is that the os.environ is a special mapping calling putenv on setitem...
98 140
  * For these reason the os.environ will be replaced by a new dict instance for

+ 26
- 2
src/responder.h View File

@@ -16,6 +16,28 @@
16 16
  * You should have received a copy of the GNU Affero General Public License
17 17
  * along with PyFCGI.  If not, see <http://www.gnu.org/licenses/>.
18 18
  */
19
+/**@defgroup work_master_proc Worker handler process
20
+ * @brief This process use the @ref responder_loop() function as "main" function
21
+ *
22
+ * @section work_master_spawn Spawning workers
23
+ * This subprocess handle worker spawning using @ref spawn(). A POSIX semaphore
24
+ * allow to know when the worker pool is idle or not :
25
+ * 
26
+ * @subsection work_master_spawn_sem Semaphore idle & busy detection
27
+ * When a new worker is ready (idle) it add 1 to the semaphore, when processing
28
+ * a request it substract 1 to the semaphore (done in @ref work() function in
29
+ * @ref worker_process )
30
+ *
31
+ * When semtimedop blocks on wait_for_zero operation it means that the pool is
32
+ * idle. Instead, if the semtimedop returns imediately it means a new worker
33
+ * can be spawned.
34
+ *
35
+ * @ingroup processes
36
+ * @ingroup main_proc
37
+ */
38
+/**@file responder.h
39
+ * @ingroup work_master_proc
40
+ */
19 41
 #ifndef _RESPONDER__H___
20 42
 #define _RESPONDER__H___
21 43
 #include "config.h"
@@ -40,7 +62,7 @@ extern int pyfcgi_semid;
40 62
 void init_context();
41 63
 
42 64
 /**@brief The responder loop
43
- *
65
+ * @ingroup work_master_proc
44 66
  * The main function of the fcgi app fork child
45 67
  * @param int max_requests : exit normally after this number of requests. If
46 68
  * 0 given never exit.
@@ -55,7 +77,7 @@ int responder_loop(char *py_entrypoint, unsigned int max_reqs,
55 77
 
56 78
 
57 79
 /**@brief Spawn a worker given an entrypoint
58
- *
80
+ * @ingroup work_master_proc
59 81
  * Spawn a new worker process and prepare ENV & request forwarding
60 82
  * @param char* python_entrypoint a path to a python entrypoint
61 83
  * @param int worker uid
@@ -66,12 +88,14 @@ int responder_loop(char *py_entrypoint, unsigned int max_reqs,
66 88
 pid_t spawn(char*, int, int, int);
67 89
 
68 90
 /**@brief Generate a new semaphore from given key
91
+ * @ingroup work_master_proc
69 92
  * @note set pyfcgi_semid
70 93
  * @return int semid
71 94
  */
72 95
 int new_semaphore();
73 96
 
74 97
 /**@brief Exit after closing all stuff like semaphores
98
+ * @ingroup work_master_proc
75 99
  */
76 100
 void clean_exit(int);
77 101
 

Loading…
Cancel
Save