Browse Source

Fixes #12 Using libpyfcgi.IoOut for stdout & stderr PEP333 workers

libpyfcgi.IoOut can be use for stdout & stderr for alternate workers too
Yann Weber 4 years ago
parent
commit
794324f494
5 changed files with 74 additions and 21 deletions
  1. 6
    1
      include/python_pyfcgi.h
  2. 2
    0
      include/pyutils.h
  3. 29
    4
      src/python_pyfcgi.c
  4. 26
    9
      src/pyutils.c
  5. 11
    7
      src/pyworker.c

+ 6
- 1
include/python_pyfcgi.h View File

@@ -63,7 +63,9 @@ struct libpyfcgi_context_s
63 63
 	 * @ingroup libpyfcgi */
64 64
 	PyObject *headers;
65 65
 	/**@brief libpyfcgi.IoIn instance */
66
-	IoIn *ioin;
66
+	PyIO_t *ioin;
67
+	/**@brief libpyfcgi.IoOut instances for stdout & stderr */
68
+	PyIO_t *stdio[2];
67 69
 	/**@brief Indicate if headers was sent in a PEP333 application
68 70
 	 * @ingroup libpyfcgi */
69 71
 	short headers_sent;
@@ -157,4 +159,7 @@ PyObject* pyfcgi_start_response(PyObject*, PyObject**, Py_ssize_t);
157 159
  */
158 160
 PyObject* pyfcgi_write_body(PyObject*, PyObject**, Py_ssize_t);
159 161
 
162
+int _libpyfcgi_stdout_write(const char*, size_t);
163
+int _libpyfcgi_stderr_write(const char*, size_t);
164
+
160 165
 #endif

+ 2
- 0
include/pyutils.h View File

@@ -72,6 +72,8 @@ PyObject* update_pyenv(PyObject*, char**);
72 72
  * from PyFCGI_conf.py_entrymod & PyFCGI_conf.py_entryfun */
73 73
 PyObject* import_entrypoint();
74 74
 
75
+/**@brief Init and return libpyfcgi */
76
+PyObject* pyinit_libpyfcgi();
75 77
 /**@brief Return the start_response() python function for pep333 worker */
76 78
 PyObject* get_start_response();
77 79
 

+ 29
- 4
src/python_pyfcgi.c View File

@@ -21,7 +21,7 @@
21 21
 
22 22
 /* Globals definitions */
23 23
 /* libpyfcgi context */
24
-libpyfcgi_context_t libpyfcgi = { NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 };
24
+libpyfcgi_context_t libpyfcgi = { NULL, NULL, NULL, NULL, {NULL, NULL}, 0, NULL, NULL, 0 };
25 25
 /* Python module methods specs */
26 26
 /**@todo Add doc in last field */
27 27
 PyMethodDef pyfcgimodule_methods[] = {
@@ -308,6 +308,12 @@ PyInit_libpyfcgi(void)
308 308
 	{
309 309
 		return NULL;
310 310
 	}
311
+	// init IoOut type
312
+	IoOutType.tp_new = PyType_GenericNew;
313
+	if(PyType_Ready(&IoOutType) < 0)
314
+	{
315
+		return NULL;
316
+	}
311 317
 
312 318
 	// init module & globals
313 319
 	libpyfcgi.status = NULL;
@@ -316,19 +322,28 @@ PyInit_libpyfcgi(void)
316 322
 	libpyfcgi.self = PyModule_Create(&pyfcgimodule);
317 323
 	if(libpyfcgi.self == NULL) { return NULL; }
318 324
 
319
-	// Add type to module (optionnal)
325
+	// Add type to module
320 326
 	PyModule_AddObject(libpyfcgi.self, "IoIn", (PyObject*)&IoInType);
327
+	PyModule_AddObject(libpyfcgi.self, "IoOut", (PyObject*)&IoOutType);
321 328
 
322 329
 	// Create a new instance of IoIn
323
-	libpyfcgi.ioin = (IoIn*)PyObject_CallObject((PyObject*)&IoInType, NULL);
330
+	libpyfcgi.ioin = (PyIO_t*)PyObject_CallObject((PyObject*)&IoInType, NULL);
324 331
 	Py_INCREF(libpyfcgi.ioin);
325 332
 	if(!libpyfcgi.ioin)
326 333
 	{
327 334
 		return NULL;
328 335
 	}
329
-	libpyfcgi.ioin->in_stream = &libpyfcgi.in; // point on stream pointer
336
+	libpyfcgi.ioin->io_stream = &libpyfcgi.in; // point on stream pointer
330 337
 	libpyfcgi.ioin->bin = 1; // binary stream (bytes for python)
331 338
 
339
+	// Add stdout & stderr
340
+pyfcgi_log(LOG_DEBUG, "libpyfcgi INIT0");
341
+	libpyfcgi.stdio[0] = (PyIO_t*)PyObject_CallObject((PyObject*)&IoOutType, NULL);
342
+pyfcgi_log(LOG_DEBUG, "libpyfcgi INIT1");
343
+	libpyfcgi.stdio[0]->write = _libpyfcgi_stdout_write;
344
+	libpyfcgi.stdio[1] = (PyIO_t*)PyObject_CallObject((PyObject*)&IoOutType, NULL);
345
+	libpyfcgi.stdio[1]->write = _libpyfcgi_stderr_write;
346
+
332 347
 	// Add it to wsgi dict
333 348
 	if(PyDict_SetItemString(PyFCGI_conf.context.wsgi_dict, "wsgi.input",
334 349
 		(PyObject*)libpyfcgi.ioin))
@@ -542,3 +557,13 @@ void libpyfcgi_timeout()
542 557
 	}
543 558
 }
544 559
 
560
+int _libpyfcgi_stdout_write(const char* buff, size_t sz)
561
+{
562
+	pyfcgi_log(LOG_INFO, "stdout : '%s'", buff);
563
+	return 1;
564
+}
565
+int _libpyfcgi_stderr_write(const char* buff, size_t sz)
566
+{
567
+	pyfcgi_log(LOG_ERR, "stderr : '%s'", buff);
568
+	return 1;
569
+}

+ 26
- 9
src/pyutils.c View File

@@ -434,19 +434,36 @@ PyObject* import_entrypoint()
434 434
 	return entry_fun;
435 435
 }
436 436
 
437
-PyObject* get_start_response()
437
+PyObject* pyinit_libpyfcgi()
438 438
 {
439 439
 	PyObject *module;
440
-	if(!libpyfcgi.self)
440
+	if(libpyfcgi.self) { return libpyfcgi.self; }
441
+
442
+	module = PyInit_libpyfcgi();
443
+	if(module == NULL)
441 444
 	{
442
-		module = PyInit_libpyfcgi();
443
-		if(module == NULL)
444
-		{
445
-			pyfcgi_log(LOG_ERR, "Unable to create libpyfcgi python module");
446
-			return NULL;
447
-		}
448
-		libpyfcgi.self = module;
445
+		pyfcgi_log(LOG_ERR, "Unable to create libpyfcgi python module");
446
+		return NULL;
447
+	}
448
+	libpyfcgi.self = module;
449
+	if(PySys_SetObject("stdout", (PyObject*)libpyfcgi.stdio[0]))
450
+	{
451
+		pyfcgi_log(LOG_ERR, "Unable to set sys.stdout");
452
+		log_expt(LOG_ALERT);
453
+		return NULL;
449 454
 	}
455
+	if(PySys_SetObject("stderr", (PyObject*)libpyfcgi.stdio[1]))
456
+	{
457
+		pyfcgi_log(LOG_ERR, "Unable to set sys.stderr");
458
+		log_expt(LOG_ALERT);
459
+		return NULL;
460
+	}
461
+	return module;
462
+}
463
+
464
+PyObject* get_start_response()
465
+{
466
+	pyinit_libpyfcgi();
450 467
 	return PyObject_GetAttrString(libpyfcgi.self, "start_response");
451 468
 }
452 469
 

+ 11
- 7
src/pyworker.c View File

@@ -39,11 +39,11 @@ static int worker_piper_sigrcv = 0;
39 39
 
40 40
 int work333(int wrk_id)
41 41
 {
42
-	PyObject *entry_fun, *pyflush[2], *py_osmod, *entry_ret, *environ,
42
+	PyObject *entry_fun, *py_osmod, *entry_ret, *environ,
43 43
 		*start_response, *args;
44 44
 	FCGX_Stream *in_stream, *out_stream, *err_stream;
45 45
 	char **envp;
46
-	int count, pipe_out[2], pipe_err[2];
46
+	int count;
47 47
 	int max_reqs;
48 48
 	struct timeval start, stop;
49 49
 	FCGX_Request *request;
@@ -54,11 +54,17 @@ int work333(int wrk_id)
54 54
 
55 55
 	pyinit();
56 56
 	pyfcgi_log(LOG_DEBUG, "Python started");
57
-	update_python_fd(pipe_out, pipe_err);
58
-	fetch_pyflush(&(pyflush[0]), &(pyflush[1]));
59
-
60 57
 	//importing os
61 58
 	py_osmod = python_osmod();
59
+	pyfcgi_log(LOG_DEBUG, "Python OSMOD");
60
+	//importing libpyfcgi
61
+	if(!pyinit_libpyfcgi())
62
+	{
63
+		exit(PYFCGI_FATAL);
64
+	}
65
+	pyfcgi_log(LOG_DEBUG, "libpyfcgi imported");
66
+
67
+
62 68
 	// loading module
63 69
 	entry_fun = import_entrypoint();
64 70
 
@@ -146,8 +152,6 @@ int work333(int wrk_id)
146 152
 		// clean stuffs
147 153
 		Py_DECREF(args);
148 154
 		Py_DECREF(environ);
149
-		// flush & logs pystdout & pystderr
150
-		worker_log_pipes(pipe_out[0], pipe_err[0], pyflush);
151 155
 
152 156
 		FCGX_FClose(out_stream);
153 157
 		FCGX_FClose(in_stream);

Loading…
Cancel
Save