/meinheld/server/server.c
C | 2612 lines | 2058 code | 352 blank | 202 comment | 415 complexity | 0158c09a4b0bbe1625830134c228a98e MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- #include "server.h"
- #include <arpa/inet.h>
- #include <signal.h>
- #ifdef linux
- #include <sys/prctl.h>
- #include <sys/socket.h>
- #endif
- #include <sys/un.h>
- #include <sys/stat.h>
- #include "http_request_parser.h"
- #include "response.h"
- #include "log.h"
- #include "client.h"
- #include "util.h"
- #include "input.h"
- #include "timer.h"
- #include "heapq.h"
- #ifdef WITH_GREENLET
- #include "greensupport.h"
- #endif
- #define ACCEPT_TIMEOUT_SECS 1
- #define READ_TIMEOUT_SECS 30
- #define READ_BUF_SIZE 1024 * 64
- typedef struct {
- TimerObject **q;
- uint32_t size;
- uint32_t max;
- } pending_queue_t;
- static char *server_name = "127.0.0.1";
- static uint16_t server_port = 8000;
- /* static int listen_sock; // listen socket */
- static PyObject *listen_socks = NULL; // listen socket
- static volatile sig_atomic_t loop_done;
- static volatile sig_atomic_t call_shutdown = 0;
- static volatile sig_atomic_t catch_signal = 0;
- static picoev_loop* main_loop = NULL; //main loop
- static heapq_t *g_timers;
- static pending_queue_t *g_pendings = NULL;
- // active event cnt
- static int activecnt = 0;
- static PyObject *wsgi_app = NULL; //wsgi app
- static uint8_t watch_loop = 0;
- static PyObject *watchdog = NULL; //watchdog
- static char is_write_access_log = 0;
- static int is_keep_alive = 0; //keep alive support
- static int keep_alive_timeout = 5;
- uint64_t max_content_length = 1024 * 1024 * 16; //max_content_length
- int client_body_buffer_size = 1024 * 500; //client_body_buffer_size
- static char *unix_sock_name = NULL;
- static int backlog = 1024 * 4; // backlog size
- static int max_fd = 1024 * 4; // picoev max_fd
- // greenlet hub switch value
- static PyObject *hub_switch_value;
- PyObject* current_client;
- PyObject* timeout_error;
- /* reuse object */
- static PyObject *client_key = NULL; //meinheld.client
- static PyObject *wsgi_input_key = NULL; //wsgi.input key
- // https://gist.github.com/mitsuhiko/5721107
- static PyObject *wsgi_input_terminated_key = NULL; //wsgi.input_terminated key
- static PyObject *status_code_key = NULL; //STATUS_CODE
- static PyObject *bytes_sent_key = NULL; // SEND_BYTES
- static PyObject *request_time_key = NULL; // REQUEST_TIME
- static PyObject *local_time_key = NULL; // LOCAL_TIME
- static PyObject *empty_string = NULL; //""
- static PyObject *app_handler_func = NULL;
- /* gunicorn */
- static time_t watchdog_lasttime;
- static int spinner = 0;
- static int tempfile_fd = 0;
- static int gtimeout = 0;
- static int ppid = 0;
- #define CLIENT_MAXFREELIST 1024
- static client_t *client_free_list[CLIENT_MAXFREELIST];
- static int client_numfree = 0;
- static void
- read_callback(picoev_loop* loop, int fd, int events, void* cb_arg);
- #ifndef WITH_GREENLET
- static void
- write_callback(picoev_loop* loop, int fd, int events, void* cb_arg);
- #endif
- static void
- kill_callback(picoev_loop* loop, int fd, int events, void* cb_arg);
- static void
- trampoline_callback(picoev_loop* loop, int fd, int events, void* cb_arg);
- static PyObject*
- internal_schedule_call(int seconds, PyObject *cb, PyObject *args, PyObject *kwargs, PyObject *greenlet);
- static int
- prepare_call_wsgi(client_t *client);
- static void
- call_wsgi_handler(client_t *client);
- static int
- check_status_code(client_t *client);
- static pending_queue_t*
- init_pendings(void)
- {
- pending_queue_t *pendings = NULL;
- pendings = PyMem_Malloc(sizeof(pending_queue_t));
- if (pendings == NULL) {
- return NULL;
- }
- pendings->size = 0;
- pendings->max= 1024;
- pendings->q = (TimerObject**)malloc(sizeof(TimerObject*) * pendings->max);
- if (pendings->q == NULL) {
- PyMem_Free(pendings);
- return NULL;
- }
- return pendings;
- }
- static int
- realloc_pendings(void)
- {
- TimerObject **new_heap;
- uint32_t max;
- pending_queue_t *pendings = g_pendings;
- if (pendings->size >= pendings->max) {
- //realloc
- max = pendings->max * 2;
- new_heap = (TimerObject**)realloc(pendings->q, sizeof(TimerObject*) * max);
- if (new_heap == NULL) {
- PyErr_SetString(PyExc_Exception, "size over timer queue");
- return -1;
- }
- pendings->max = max;
- pendings->q = new_heap;
- RDEBUG("realloc max:%d", pendings->max);
- }
- return 1;
- }
- static void
- destroy_pendings(void)
- {
- int i = 0, len;
- TimerObject *timer = NULL;
- TimerObject **t = g_pendings->q;
- if (g_pendings == NULL) {
- return;
- }
- len = g_pendings->size;
- t += i;
- while(len--) {
- timer = *t;
- Py_DECREF(timer);
- t++;
- }
- free(g_pendings->q);
- PyMem_Free(g_pendings);
- g_pendings = NULL;
- }
- static void
- client_t_list_fill(void)
- {
- client_t *client;
- while (client_numfree < CLIENT_MAXFREELIST) {
- client = (client_t *)PyMem_Malloc(sizeof(client_t));
- client_free_list[client_numfree++] = client;
- }
- }
- static void
- client_t_list_clear(void)
- {
- client_t *op;
- while (client_numfree) {
- op = client_free_list[--client_numfree];
- PyMem_Free(op);
- }
- }
- static client_t*
- alloc_client_t(void)
- {
- client_t *client;
- if (client_numfree) {
- client = client_free_list[--client_numfree];
- GDEBUG("use pooled %p", client);
- } else {
- client = (client_t *)PyMem_Malloc(sizeof(client_t));
- GDEBUG("alloc %p", client);
- }
- memset(client, 0, sizeof(client_t));
- return client;
- }
- static void
- dealloc_client(client_t *client)
- {
- if (client_numfree < CLIENT_MAXFREELIST) {
- client_free_list[client_numfree++] = client;
- GDEBUG("back to pool %p", client);
- } else {
- PyMem_Free(client);
- }
- }
- static client_t *
- new_client_t(int client_fd, char *remote_addr, uint32_t remote_port)
- {
- client_t *client;
- client = alloc_client_t();
- //client = PyMem_Malloc(sizeof(client_t));
- //memset(client, 0, sizeof(client_t));
- client->fd = client_fd;
- client->complete = 1;
- client->request_queue = new_request_queue();
- client->remote_addr = remote_addr;
- client->remote_port = remote_port;
- /* client->body_type = BODY_TYPE_NONE; */
- GDEBUG("client alloc %p", client);
- return client;
- }
- static void
- set_log_value(client_t *client, PyObject *environ, uintptr_t delta_msec)
- {
- PyObject *status_code = NULL, *bytes = NULL, *request_time = NULL, *local_time = NULL;
- status_code = PyLong_FromLong(client->status_code);
- bytes = PyLong_FromLong(client->write_bytes);
- request_time = PyLong_FromLong(delta_msec);
- local_time = NATIVE_FROMSTRING((char*)http_log_time);
- if (status_code) {
- PyDict_SetItem(environ, status_code_key, status_code);
- Py_DECREF(status_code);
- }
- if (bytes) {
- PyDict_SetItem(environ, bytes_sent_key, bytes);
- Py_DECREF(bytes);
- }
- if (request_time) {
- PyDict_SetItem(environ, request_time_key, request_time);
- Py_DECREF(request_time);
- }
- if (local_time) {
- PyDict_SetItem(environ, local_time_key, local_time);
- Py_DECREF(local_time);
- }
- }
- static void
- clean_client(client_t *client)
- {
- PyObject *environ = NULL;
- uintptr_t end, delta_msec = 0;
- request *req = client->current_req;
- if (is_write_access_log) {
- DEBUG("write access log");
- cache_time_update();
- if (req) {
- environ = req->environ;
- end = current_msec;
- if (req->start_msec > 0){
- delta_msec = end - req->start_msec;
- }
- set_log_value(client, environ, delta_msec);
- call_access_logger(environ);
- } else {
- if (client->status_code != 408) {
- environ = new_environ(client);
- set_log_value(client, environ, delta_msec);
- call_access_logger(environ);
- }
- }
- }
- Py_CLEAR(client->http_status);
- Py_CLEAR(client->headers);
- Py_CLEAR(client->response_iter);
- Py_CLEAR(client->response);
- if (req == NULL) {
- goto init;
- }
- DEBUG("status_code:%d env:%p", client->status_code, req->environ);
- if (req->environ) {
- /* PyDict_Clear(client->environ); */
- /* DEBUG("CLEAR environ"); */
- Py_CLEAR(req->environ);
- }
- if (req->body) {
- if (req->body_type == BODY_TYPE_TMPFILE) {
- fclose(req->body);
- } else {
- free_buffer(req->body);
- }
- req->body = NULL;
- }
- free_request(req);
- init:
- client->current_req = NULL;
- client->header_done = 0;
- client->response_closed = 0;
- client->chunked_response = 0;
- client->content_length_set = 0;
- client->content_length = 0;
- client->write_bytes = 0;
- }
- static void
- close_client(client_t *client)
- {
- client_t *new_client = NULL;
- int ret;
- if (!client->response_closed) {
- close_response(client);
- }
- DEBUG("start close client:%p fd:%d status_code %d", client, client->fd, client->status_code);
- if (picoev_is_active(main_loop, client->fd)) {
- if (!picoev_del(main_loop, client->fd)) {
- activecnt--;
- DEBUG("activecnt:%d", activecnt);
- }
- DEBUG("picoev_del client:%p fd:%d", client, client->fd);
- }
- clean_client(client);
- DEBUG("remain http pipeline size :%d", client->request_queue->size);
- if (client->request_queue->size > 0) {
- if (check_status_code(client) > 0) {
- //process pipeline
- if (prepare_call_wsgi(client) > 0) {
- call_wsgi_handler(client);
- }
- }
- return ;
- }
- if (client->http_parser != NULL) {
- /* PyMem_Free(client->http_parser); */
- dealloc_parser(client->http_parser);
- }
- free_request_queue(client->request_queue);
- if (!client->keep_alive) {
- close(client->fd);
- BDEBUG("close client:%p fd:%d", client, client->fd);
- } else {
- BDEBUG("keep alive client:%p fd:%d", client, client->fd);
- new_client = new_client_t(client->fd, client->remote_addr, client->remote_port);
- new_client->keep_alive = 1;
- init_parser(new_client, server_name, server_port);
- ret = picoev_add(main_loop, new_client->fd, PICOEV_READ, keep_alive_timeout, read_callback, (void *)new_client);
- if (ret == 0) {
- activecnt++;
- }
- }
- //clear old client
- dealloc_client(client);
- }
- static void init_main_loop(void)
- {
- if (main_loop == NULL) {
- /* init picoev */
- picoev_init(max_fd);
- /* create loop */
- main_loop = picoev_create_loop(60);
- }
- }
- static void
- kill_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
- {
- picoev_del(loop, fd);
- if ((events & PICOEV_TIMEOUT) != 0) {
- DEBUG("force shutdown...");
- loop_done = 0;
- }
- }
- static inline void
- kill_server(int timeout)
- {
- int listen_sock = 0;
- PyObject *iter = NULL, *item;
- int set_callback = 0;
- if (main_loop == NULL) {
- return;
- }
- iter = PyObject_GetIter(listen_socks);
- if (PyErr_Occurred()){
- call_error_logger();
- return;
- }
- while((item = PyIter_Next(iter))){
- #ifdef PY3
- if (PyLong_Check(item)) {
- listen_sock = (int)PyLong_AsLong(item);
- #else
- if (PyInt_Check(item)) {
- listen_sock = (int)PyInt_AsLong(item);
- #endif
- //stop accepting
- if (!picoev_del(main_loop, listen_sock)) {
- activecnt--;
- DEBUG("activecnt:%d", activecnt);
- }
- if (!set_callback) {
- //shutdown timeout
- if (timeout > 0) {
- //set timeout
- (void)picoev_add(main_loop, listen_sock, PICOEV_TIMEOUT, timeout, kill_callback, NULL);
- } else {
- (void)picoev_add(main_loop, listen_sock, PICOEV_TIMEOUT, 1, kill_callback, NULL);
- }
- set_callback = 1;
- }
- } else {
- //TODO WARN???
- }
- Py_DECREF(item);
- }
- Py_DECREF(iter);
- }
- static inline void
- set_current_request(client_t *client)
- {
- request *req;
- req = shift_request(client->request_queue);
- client->current_req = req;
- }
- static void
- set_bad_request_code(client_t *client, int status_code)
- {
- request *req;
- req = client->request_queue->tail;
- req->bad_request_code = status_code;
- DEBUG("set bad request code %d", status_code);
- }
- static int
- check_status_code(client_t *client)
- {
- request *req;
- req = client->request_queue->head;
- if (req && req->bad_request_code > 200) {
- //error
- //shift
- DEBUG("bad status code %d", req->bad_request_code);
- set_current_request(client);
- client->status_code = req->bad_request_code;
- send_error_page(client);
- close_client(client);
- return -1;
- }
- return 1;
- }
- static PyObject *
- app_handler(PyObject *self, PyObject *args)
- {
- int ret, active;
- PyObject *wsgi_args = NULL, *start = NULL, *current = NULL, *parent = NULL, *res = NULL;
- PyObject *env = NULL;
- ClientObject *pyclient;
- client_t *client;
- request *req;
- response_status status;
- if (!PyArg_ParseTuple(args, "O:app_handler", &env)) {
- return NULL;
- }
- pyclient = (ClientObject*)PyDict_GetItem(env, client_key);
- client = pyclient->client;
- req = client->current_req;
- start = create_start_response(client);
- if (!start) {
- return NULL;
- }
- DEBUG("call wsgi app");
- wsgi_args = PyTuple_Pack(2, env, start);
- res = PyObject_CallObject(wsgi_app, wsgi_args);
- Py_DECREF(wsgi_args);
- DEBUG("called wsgi app");
- //check response & PyErr_Occurred
- if (res && res == Py_None) {
- PyErr_SetString(PyExc_Exception, "response must be a iter or sequence object");
- goto error;
- }
- //Check wsgi_app error
- if (PyErr_Occurred()) {
- goto error;
- }
- client->response = res;
- if (client->response_closed) {
- //closed
- close_client(client);
- Py_RETURN_NONE;
- }
- status = response_start(client);
- #ifdef WITH_GREENLET
- while(status != STATUS_OK) {
- if (status == STATUS_ERROR) {
- // Internal Server Error
- req->bad_request_code = 500;
- goto error;
- } else {
- active = picoev_is_active(main_loop, client->fd);
- ret = picoev_add(main_loop, client->fd, PICOEV_WRITE, 300, trampoline_callback, (void *)pyclient);
- if ((ret == 0 && !active)) {
- activecnt++;
- }
- // switch to hub
- current = pyclient->greenlet;
- parent = greenlet_getparent(current);
- /* Py_INCREF(hub_switch_value); */
- res = greenlet_switch(parent, hub_switch_value, NULL);
- Py_XDECREF(res);
- // try again after event switch
- status = process_body(client);
- }
- }
- status = close_response(client);
- if (status == STATUS_ERROR) {
- //TODO logging error
- }
- // send OK
- close_client(client);
- #else
- switch(status) {
- case STATUS_ERROR:
- // Internal Server Error
- req->bad_request_code = 500;
- goto error;
- case STATUS_SUSPEND:
- // continue
- // set callback
- active = picoev_is_active(main_loop, client->fd);
- ret = picoev_add(main_loop, client->fd, PICOEV_WRITE, 300, write_callback, (void *)pyclient);
- if ((ret == 0 && !active)) {
- activecnt++;
- }
- default:
- // send OK
- close_client(client);
- }
- #endif
- Py_RETURN_NONE;
- error:
- client->status_code = 500;
- status = close_response(client);
- if (status == STATUS_ERROR) {
- //TODO logging error
- }
- /* write_error_log(__FILE__, __LINE__); */
- call_error_logger();
- send_error_page(client);
- close_client(client);
- Py_RETURN_NONE;
- }
- static PyMethodDef app_handler_def = {"_app_handler", (PyCFunction)app_handler, METH_VARARGS, 0};
- static PyObject*
- get_app_handler(void)
- {
- if (app_handler_func == NULL) {
- app_handler_func = PyCFunction_NewEx(&app_handler_def, (PyObject *)NULL, NULL);
- }
- //Py_INCREF(app_handler_func);
- return app_handler_func;
- }
- #ifdef WITH_GREENLET
- static void
- resume_greenlet(PyObject *greenlet)
- {
- PyObject *res = NULL;
- PyObject *err_type, *err_val, *err_tb;
- if (PyErr_Occurred()) {
- PyErr_Fetch(&err_type, &err_val, &err_tb);
- PyErr_Clear();
- //set error
- res = greenlet_throw(greenlet, err_type, err_val, err_tb);
- } else {
- /* Py_INCREF(hub_switch_value); */
- res = greenlet_switch(greenlet, hub_switch_value, NULL);
- if (res == NULL) {
- call_error_logger();
- /* PyErr_Fetch(&err_type, &err_val, &err_tb); */
- /* PyErr_Clear(); */
- //set error
- /* res = greenlet_throw(greenlet, err_type, err_val, err_tb); */
- }
- }
- Py_XDECREF(res);
- if (greenlet_dead(greenlet)) {
- Py_DECREF(greenlet);
- }
- }
- static void
- resume_wsgi_handler(ClientObject *pyclient)
- {
- PyObject *res = NULL;
- PyObject *err_type, *err_val, *err_tb;
- client_t *old_client;
- client_t *client = pyclient->client;
- //swap bind client_t
- old_client = start_response->cli;
- start_response->cli = client;
- current_client = (PyObject *)pyclient;
- if (PyErr_Occurred()) {
- PyErr_Fetch(&err_type, &err_val, &err_tb);
- PyErr_Clear();
- //set error
- res = greenlet_throw(pyclient->greenlet, err_type, err_val, err_tb);
- } else {
- res = greenlet_switch(pyclient->greenlet, pyclient->args, pyclient->kwargs);
- }
- start_response->cli = old_client;
- Py_CLEAR(pyclient->args);
- Py_CLEAR(pyclient->kwargs);
- Py_XDECREF(res);
- }
- #endif
- static void
- call_wsgi_handler(client_t *client)
- {
- PyObject *handler, *greenlet, *args, *res;
- ClientObject *pyclient;
- request *req = NULL;
- handler = get_app_handler();
- req = client->current_req;
- current_client = PyDict_GetItem(req->environ, client_key);
- pyclient = (ClientObject *)current_client;
- args = PyTuple_Pack(1, req->environ);
- #ifdef WITH_GREENLET
- //new greenlet
- greenlet = greenlet_new(handler, NULL);
- // set_greenlet
- pyclient->greenlet = greenlet;
- Py_INCREF(pyclient->greenlet);
- res = greenlet_switch(greenlet, args, NULL);
- //res = PyObject_CallObject(wsgi_app, args);
- Py_DECREF(args);
- Py_DECREF(greenlet);
- #else
- pyclient->greenlet = NULL;
- res = PyObject_CallObject(handler, args);
- Py_DECREF(args);
- #endif
- Py_XDECREF(res);
- }
- #ifdef WITH_GREENLET
- static void
- timeout_error_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
- {
- ClientObject *pyclient = (ClientObject *)(cb_arg);
- client_t *client = pyclient->client;
- if ((events & PICOEV_TIMEOUT) != 0) {
- DEBUG("timeout_error_callback pyclient:%p client:%p fd:%d", pyclient, pyclient->client, pyclient->client->fd);
- if (!picoev_del(loop, fd)) {
- activecnt--;
- DEBUG("activecnt:%d", activecnt);
- }
- pyclient->suspended = 0;
- /* pyclient->resumed = 1; */
- PyErr_SetString(timeout_error, "timeout");
- set_so_keepalive(client->fd, 0);
- resume_wsgi_handler(pyclient);
- }
- }
- static void
- timeout_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
- {
- ClientObject *pyclient = (ClientObject *)(cb_arg);
- client_t *client = pyclient->client;
- if ((events & PICOEV_TIMEOUT) != 0) {
- DEBUG("timeout_callback pyclient:%p client:%p fd:%d", pyclient, pyclient->client, pyclient->client->fd);
- //next intval 30sec
- picoev_set_timeout(loop, client->fd, 30);
- // is_active ??
- if (write(client->fd, "", 0) < 0) {
- if (!picoev_del(loop, fd)) {
- activecnt--;
- DEBUG("activecnt:%d", activecnt);
- }
- //resume
- pyclient->suspended = 0;
- /* pyclient->resumed = 1; */
- PyErr_SetFromErrno(PyExc_IOError);
- DEBUG("closed");
- set_so_keepalive(client->fd, 0);
- resume_wsgi_handler(pyclient);
- }
- }
- }
- static void
- trampoline_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
- {
- PyObject *o = NULL;
- ClientObject *pyclient = NULL;
- client_t *client = NULL;
- if (!picoev_del(loop, fd)) {
- activecnt--;
- DEBUG("activecnt:%d", activecnt);
- }
- YDEBUG("call trampoline_callback fd:%d event:%d cb_arg:%p", fd, events, cb_arg);
- o = (PyObject*)cb_arg;
- if (CheckClientObject(o)) {
- pyclient = (ClientObject*)cb_arg;
- client = pyclient->client;
- if ((events & PICOEV_TIMEOUT) != 0) {
- RDEBUG("** trampoline_callback timeout **");
- //timeout
- client->keep_alive = 0;
- PyErr_SetString(timeout_error, "timeout");
- }
- YDEBUG("resume_wsgi_handler");
- resume_wsgi_handler(pyclient);
- } else if (greenlet_check(o)) {
- YDEBUG("resume_greenlet");
- resume_greenlet(o);
- }
- }
- #endif
- #ifndef WITH_GREENLET
- static void
- write_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
- {
- ClientObject *pyclient = (ClientObject*)cb_arg;
- client_t *client = pyclient->client;
- int ret;
- DEBUG("call write_callback");
- current_client = (PyObject*)pyclient;
- if ((events & PICOEV_TIMEOUT) != 0) {
- DEBUG("** write_callback timeout **");
- //timeout
- client->keep_alive = 0;
- close_client(client);
- } else if ((events & PICOEV_WRITE) != 0) {
- ret = process_body(client);
- DEBUG("process_body ret %d", ret);
- if (ret != 0) {
- //ok or die
- close_client(client);
- }
- }
- }
- #endif
- static int
- check_http_expect(client_t *client)
- {
- PyObject *c = NULL;
- char *val = NULL;
- int ret;
- request *req = client->current_req;
- if (client->http_parser->http_minor == 1) {
- ///TODO CHECK
- c = PyDict_GetItemString(req->environ, "HTTP_EXPECT");
- if (c) {
- #ifdef PY3
- val = PyUnicode_AsUTF8(c);
- #else
- val = PyBytes_AS_STRING(c);
- #endif
- if (!strncasecmp(val, "100-continue", 12)) {
- ret = write(client->fd, "HTTP/1.1 100 Continue\r\n\r\n", 25);
- if (ret < 0) {
- //fail
- PyErr_SetFromErrno(PyExc_IOError);
- /* write_error_log(__FILE__, __LINE__); */
- call_error_logger();
- client->keep_alive = 0;
- client->status_code = 500;
- send_error_page(client);
- close_client(client);
- return -1;
- }
- } else {
- //417
- client->keep_alive = 0;
- client->status_code = 417;
- send_error_page(client);
- close_client(client);
- return -1;
- }
- }
- return 1;
- }
- return 0;
- }
- #ifdef PY3
- static int
- set_input_file(client_t *client)
- {
- PyObject *input;
- int fd;
- request *req = client->current_req;
- FILE *tmp = (FILE *)req->body;
- fflush(tmp);
- rewind(tmp);
- fd = fileno(tmp);
- input = PyFile_FromFd(fd, "<tmpfile>", "rb", -1, NULL, NULL, NULL, 1);
- if (input == NULL) {
- fclose(tmp);
- req->body = NULL;
- return -1;
- }
- //env["wsgi.input"] = tmpfile
- //
- PyDict_SetItem((PyObject *)req->environ, wsgi_input_key, input);
- Py_DECREF(input);
- req->body = NULL;
- return 1;
- }
- #else
- static int
- set_input_file(client_t *client)
- {
- PyObject *input;
- request *req = client->current_req;
- FILE *tmp = (FILE *)req->body;
- fflush(tmp);
- rewind(tmp);
- input = PyFile_FromFile(tmp, "<tmpfile>", "r", fclose);
- if (input == NULL) {
- fclose(tmp);
- req->body = NULL;
- return -1;
- }
- //env["wsgi.input"] = tmpfile
- //
- PyDict_SetItem((PyObject *)req->environ, wsgi_input_key, input);
- Py_DECREF(input);
- req->body = NULL;
- return 0;
- }
- #endif
- static int
- set_input_object(client_t *client)
- {
- PyObject *input = NULL;
- request *req = client->current_req;
- if (req->body_type == BODY_TYPE_BUFFER) {
- input = InputObject_New((buffer_t*)req->body);
- } else {
- if (req->body) {
- input = InputObject_New((buffer_t*)req->body);
- } else {
- input = InputObject_New(new_buffer(0, 0));
- }
- }
- if (input == NULL) {
- return -1;
- }
- PyDict_SetItem((PyObject *)req->environ, wsgi_input_key, input);
- Py_DECREF(input);
- req->body = NULL;
- return 1;
- }
- /*
- static void
- setting_keepalive(client_t *client)
- {
- PyObject *c;
- char *val;
- if (is_keep_alive) {
- //support keep-alive
- c = PyDict_GetItemString(client->environ, "HTTP_CONNECTION");
- if (client->http_parser->http_minor == 1) {
- //HTTP 1.1
- if (c) {
- val = PyBytes_AS_STRING(c);
- if (!strcasecmp(val, "close")) {
- client->keep_alive = 0;
- } else {
- client->keep_alive = 1;
- }
- } else {
- client->keep_alive = 1;
- }
- } else {
- //HTTP 1.0
- if (c) {
- val = PyBytes_AS_STRING(c);
- if (!strcasecmp(val, "keep-alive")) {
- client->keep_alive = 1;
- } else {
- client->keep_alive = 0;
- }
- } else {
- client->keep_alive = 0;
- }
- }
- }
- }
- */
- static int
- prepare_call_wsgi(client_t *client)
- {
- request *req = NULL;
- set_current_request(client);
- req = client->current_req;
- //check Expect
- if (check_http_expect(client) < 0) {
- return -1;
- }
- if (req->body_type == BODY_TYPE_TMPFILE) {
- if (set_input_file(client) == -1) {
- return -1;
- }
- } else {
- if (set_input_object(client) == -1) {
- return -1;
- }
- }
- PyDict_SetItem((PyObject *)req->environ, wsgi_input_terminated_key, Py_True);
- if (!is_keep_alive) {
- client->keep_alive = 0;
- }
- /* setting_keepalive(client); */
- return 1;
- }
- static int
- set_read_error(client_t *client, int status_code)
- {
- client->keep_alive = 0;
- if (status_code == 0) {
- // bad request
- status_code = 400;
- }
- if (client->request_queue->size > 0) {
- //piplining
- set_bad_request_code(client, status_code);
- //finish = 1
- return 1;
- } else {
- if (!client->complete) {
- // read error while reading request.
- client->status_code = status_code;
- send_error_page(client);
- } // else keepalive timeout. should not send any data.
- close_client(client);
- return -1;
- }
- }
- static int
- read_timeout(int fd, client_t *client)
- {
- RDEBUG("** read timeout fd:%d", fd);
- //timeout
- return set_read_error(client, 408);
- }
- static int
- compare_key(PyObject *env, char *key, char *compare)
- {
- int ret = -1;
- char *val = NULL;
- PyObject *c = PyDict_GetItemString(env, key);
- if (c) {
- #ifdef PY3
- c = PyUnicode_AsLatin1String(c);
- val = PyBytes_AS_STRING(c);
- #else
- val = PyBytes_AS_STRING(c);
- Py_INCREF(c);
- #endif
- ret = strcasecmp(val, compare);
- }
- Py_XDECREF(c);
- return ret;
- }
- static int
- check_websocket(PyObject *env)
- {
- //Support only RFC6455
- if (PyMapping_HasKeyString(env, "HTTP_SEC_WEBSOCKET_KEY") == 1) {
- if (compare_key(env, "HTTP_SEC_WEBSOCKET_VERSION", "13") == 0) {
- return 1;
- }
- }
- return -1;
- }
- static int
- parse_new_protocol(request *req, char *buf, ssize_t readed, int nread)
- {
- PyObject *env, *c;
- char *val = NULL;
- env = req->environ;
- c = PyDict_GetItemString(env, "HTTP_UPGRADE");
- if (c) {
- #ifdef PY3
- c = PyUnicode_AsLatin1String(c);
- val = PyBytes_AS_STRING(c);
- #else
- val = PyBytes_AS_STRING(c);
- Py_INCREF(c);
- #endif
- DEBUG("Upgrade protocol %s", val);
- if (!strcasecmp(val, "websocket")) {
- Py_DECREF(c);
- //Support only RFC6455
- return check_websocket(env);
- }
- }
- // protocol not found error
- PyErr_SetString(PyExc_IOError,"unknow protocol");
- return -1;
- }
- static int
- parse_http_request(int fd, client_t *client, char *buf, ssize_t r)
- {
- int nread = 0;
- request *req = NULL;
- BDEBUG("fd:%d \n%.*s", fd, (int)r, buf);
- nread = execute_parse(client, buf, r);
- BDEBUG("read request fd %d readed %d nread %d", fd, (int)r, nread);
- req = client->current_req;
- if (client->upgrade) {
- //TODO New protocol
- if (parse_new_protocol(req, buf, r, nread) == -1) {
- return set_read_error(client, req->bad_request_code);
- }
- } else if (req == NULL) {
- DEBUG("fd %d bad_request code 400", fd);
- return set_read_error(client, 400);
- } else if (nread != r || req->bad_request_code > 0) {
- DEBUG("fd %d bad_request code %d", fd, req->bad_request_code);
- return set_read_error(client, req->bad_request_code);
- }
- if (parser_finish(client) > 0) {
- return 1;
- }
- return 0;
- }
- static int
- read_request(picoev_loop *loop, int fd, client_t *client, char call_time_update)
- {
- char buf[READ_BUF_SIZE];
- ssize_t r;
- if (!client->keep_alive) {
- picoev_set_timeout(loop, fd, READ_TIMEOUT_SECS);
- }
- Py_BEGIN_ALLOW_THREADS
- r = read(client->fd, buf, sizeof(buf));
- Py_END_ALLOW_THREADS
- switch (r) {
- case 0:
- return set_read_error(client, 503);
- case -1:
- // Error
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- // try again later
- return 0;
- } else {
- // Fatal error
- client->keep_alive = 0;
- if (errno == ECONNRESET) {
- client->header_done = 1;
- client->response_closed = 1;
- } else {
- PyErr_SetFromErrno(PyExc_IOError);
- /* write_error_log(__FILE__, __LINE__); */
- call_error_logger();
- }
- return set_read_error(client, 500);
- }
- default:
- if (call_time_update) {
- cache_time_update();
- }
- return parse_http_request(fd, client, buf, r);
- }
- }
- static void
- read_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
- {
- client_t *client = ( client_t *)(cb_arg);
- int finish = 0;
- if ((events & PICOEV_TIMEOUT) != 0) {
- finish = read_timeout(fd, client);
- } else if ((events & PICOEV_READ) != 0) {
- finish = read_request(loop, fd, client, 0);
- }
- if (finish == 1) {
- if (!picoev_del(main_loop, client->fd)) {
- activecnt--;
- DEBUG("activecnt:%d", activecnt);
- }
- if (check_status_code(client) > 0) {
- //current request ok
- if (prepare_call_wsgi(client) > 0) {
- call_wsgi_handler(client);
- }
- }
- return;
- }
- }
- static void
- accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
- {
- int client_fd, ret;
- client_t *client;
- struct sockaddr_in client_addr;
- char *remote_addr;
- uint32_t remote_port;
- int finish = 0;
- if ((events & PICOEV_TIMEOUT) != 0) {
- // time out
- // next turn or other process
- return;
- } else if ((events & PICOEV_READ) != 0) {
- int i;
- socklen_t client_len = sizeof(client_addr);
- for (i=0; i<8; ++i) {
- #if linux && defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC)
- client_fd = accept4(fd, (struct sockaddr *)&client_addr, &client_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
- #else
- client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len);
- #endif
- if (client_fd != -1) {
- DEBUG("accept fd %d", client_fd);
- //printf("connected: %d\n", client_fd);
- if (setup_sock(client_fd) == -1) {
- PyErr_SetFromErrno(PyExc_IOError);
- /* write_error_log(__FILE__, __LINE__); */
- call_error_logger();
- // die
- loop_done = 0;
- return;
- }
- remote_addr = inet_ntoa (client_addr.sin_addr);
- remote_port = ntohs(client_addr.sin_port);
- client = new_client_t(client_fd, remote_addr, remote_port);
- init_parser(client, server_name, server_port);
- finish = read_request(loop, fd, client, 1);
- if (finish == 1) {
- if (check_status_code(client) > 0) {
- //current request ok
- if (prepare_call_wsgi(client) > 0) {
- call_wsgi_handler(client);
- }
- }
- } else if (finish == 0) {
- ret = picoev_add(loop, client_fd, PICOEV_READ, keep_alive_timeout, read_callback, (void *)client);
- if (ret == 0) {
- activecnt++;
- }
- }
- } else {
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- PyErr_SetFromErrno(PyExc_IOError);
- /* write_error_log(__FILE__, __LINE__); */
- call_error_logger();
- // die
- kill_server(0);
- }
- break;
- }
- }
- }
- }
- static void
- setup_server_env(void)
- {
- /* setup_listen_sock(listen_sock); */
- cache_time_init();
- setup_static_env(server_name, server_port);
- setup_start_response();
- ClientObject_list_fill();
- client_t_list_fill();
- parser_list_fill();
- request_list_fill();
- buffer_list_fill();
- InputObject_list_fill();
- client_key = NATIVE_FROMSTRING("meinheld.client");
- wsgi_input_key = NATIVE_FROMSTRING("wsgi.input");
- wsgi_input_terminated_key = NATIVE_FROMSTRING("wsgi.input_terminated");
- status_code_key = NATIVE_FROMSTRING("STATUS_CODE");
- bytes_sent_key = NATIVE_FROMSTRING("SEND_BYTES");
- request_time_key = NATIVE_FROMSTRING("REQUEST_TIME");
- local_time_key = NATIVE_FROMSTRING("LOCAL_TIME");
- empty_string = NATIVE_FROMSTRING("");
- }
- static void
- clear_server_env(void)
- {
- //clean
- clear_start_response();
- clear_static_env();
- client_t_list_clear();
- parser_list_clear();
- ClientObject_list_clear();
- request_list_clear();
- buffer_list_clear();
- InputObject_list_clear();
- Py_DECREF(client_key);
- Py_DECREF(wsgi_input_key);
- Py_DECREF(wsgi_input_terminated_key);
- Py_DECREF(status_code_key);
- Py_DECREF(bytes_sent_key);
- Py_DECREF(request_time_key);
- Py_DECREF(local_time_key);
- Py_DECREF(empty_string);
- }
- static int
- inet_listen(void)
- {
- struct addrinfo hints, *servinfo, *p;
- int flag = 1;
- int res;
- char strport[7];
- int listen_sock = 0;
- PyObject *fd = NULL;
- memset(&hints, 0, sizeof hints);
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
- snprintf(strport, sizeof (strport), "%d", server_port);
- if ((res = getaddrinfo(server_name, strport, &hints, &servinfo)) == -1) {
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- // loop through all the results and bind to the first we can
- for(p = servinfo; p != NULL; p = p->ai_next) {
- if ((listen_sock = socket(p->ai_family, p->ai_socktype,
- p->ai_protocol)) == -1) {
- //perror("server: socket");
- continue;
- }
- if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
- sizeof(int)) == -1) {
- close(listen_sock);
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- Py_BEGIN_ALLOW_THREADS
- res = bind(listen_sock, p->ai_addr, p->ai_addrlen);
- Py_END_ALLOW_THREADS
- if (res == -1) {
- close(listen_sock);
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- break;
- }
- if (p == NULL) {
- close(listen_sock);
- PyErr_SetString(PyExc_IOError,"server: failed to bind\n");
- return -1;
- }
- freeaddrinfo(servinfo); // all done with this structure
- // BACKLOG
- Py_BEGIN_ALLOW_THREADS
- res = listen(listen_sock, backlog);
- Py_END_ALLOW_THREADS
- if (res == -1) {
- close(listen_sock);
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- #ifdef PY3
- fd = PyLong_FromLong((long) listen_sock);
- #else
- fd = PyInt_FromLong((long) listen_sock);
- #endif
- listen_socks = PyList_New(0);
- if (PyList_Append(listen_socks, fd) == -1) {
- return -1;
- }
- Py_DECREF(fd);
- return 1;
- }
- static int
- check_unix_sockpath(char *sock_name)
- {
- if (!access(sock_name, F_OK)) {
- if (unlink(sock_name) < 0) {
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- }
- return 1;
- }
- static int
- unix_listen(char *sock_name, int len)
- {
- int listen_sock = 0;
- int flag = 1;
- int res;
- struct sockaddr_un saddr;
- mode_t old_umask;
- PyObject *fd;
- DEBUG("unix domain socket %s", sock_name);
- if (len >= sizeof(saddr.sun_path)) {
- PyErr_SetString(PyExc_OSError, "AF_UNIX path too long");
- return -1;
- }
- memset(&saddr, 0, sizeof(saddr));
- if (check_unix_sockpath(sock_name) == -1) {
- return -1;
- }
- if ((listen_sock = socket(AF_UNIX, SOCK_STREAM,0)) == -1) {
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
- sizeof(int)) == -1) {
- close(listen_sock);
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- saddr.sun_family = PF_UNIX;
- strncpy(saddr.sun_path, sock_name, len);
- old_umask = umask(0);
- Py_BEGIN_ALLOW_THREADS
- res = bind(listen_sock, (struct sockaddr *)&saddr, sizeof(saddr));
- Py_END_ALLOW_THREADS
- if (res == -1) {
- close(listen_sock);
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- umask(old_umask);
- // BACKLOG 1024
- Py_BEGIN_ALLOW_THREADS
- res = listen(listen_sock, backlog);
- Py_END_ALLOW_THREADS
- if (res == -1) {
- close(listen_sock);
- PyErr_SetFromErrno(PyExc_IOError);
- return -1;
- }
- unix_sock_name = sock_name;
- #ifdef PY3
- fd = PyLong_FromLong((long) listen_sock);
- #else
- fd = PyInt_FromLong((long) listen_sock);
- #endif
- listen_socks = PyList_New(0);
- if (PyList_Append(listen_socks, fd) == -1) {
- return -1;
- }
- Py_DECREF(fd);
- return 1;
- }
- static void
- fast_notify(void)
- {
- spinner = (spinner + 1) % 2;
- fchmod(tempfile_fd, spinner);
- if (ppid != getppid()) {
- kill_server(gtimeout);
- tempfile_fd = 0;
- }
- }
- static PyObject*
- set_listen_socket(PyObject *temp)
- {
- if (listen_socks != NULL) {
- PyErr_SetString(PyExc_Exception, "already set listen socket");
- return NULL;
- }
- #ifdef PY3
- if (PyLong_Check(temp)) {
- #else
- if (PyInt_Check(temp)) {
- #endif
- listen_socks = PyList_New(0);
- if (PyList_Append(listen_socks, temp) == -1) {
- return NULL;
- }
- Py_DECREF(temp);
- } else if (PyList_Check(temp)) {
- listen_socks = temp;
- Py_INCREF(listen_socks);
- } else {
- PyErr_SetString(PyExc_TypeError, "must be list or int");
- return NULL;
- }
- Py_RETURN_NONE;
- }
- static PyObject *
- meinheld_listen(PyObject *self, PyObject *args, PyObject *kwds)
- {
- PyObject *o = NULL;
- PyObject *sock_fd = NULL;
- char *path;
- int ret, len;
- static char *kwlist[] = {"address", "socket_fd", 0};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:listen",
- kwlist, &o, &sock_fd)) {
- return NULL;
- }
- if (listen_socks != NULL) {
- PyErr_SetString(PyExc_Exception, "already set listen socket");
- return NULL;
- }
- if (o == NULL && sock_fd != NULL) {
- return set_listen_socket(sock_fd);
- } else if (PyTuple_Check(o)) {
- //inet
- if (!PyArg_ParseTuple(o, "si:listen", &server_name, &server_port)) {
- return NULL;
- }
- ret = inet_listen();
- } else if (PyBytes_Check(o)) {
- // unix domain
- if (!PyArg_Parse(o, "s#", &path, &len)) {
- return NULL;
- }
- ret = unix_listen(path, len);
- } else {
- PyErr_SetString(PyExc_TypeError, "args tuple or string(path)");
- return NULL;
- }
- if (ret < 0) {
- //error
- return NULL;
- }
- Py_RETURN_NONE;
- }
- static void
- sigint_cb(int signum)
- {
- DEBUG("call SIGINT");
- if (!catch_signal) {
- catch_signal = signum;
- }
- }
- static void
- sigpipe_cb(int signum)
- {
- DEBUG("call SIGPIPE");
- }
- static PyObject *
- meinheld_access_log(PyObject *self, PyObject *args)
- {
- PyObject *o = NULL;
- PyObject *func = NULL;
- if (!PyArg_ParseTuple(args, "O:access_logger", &o)) {
- return NULL;
- }
- if (o == Py_None) {
- is_write_access_log = 0;
- set_access_logger(NULL);
- Py_RETURN_NONE;
- }
- func = PyObject_GetAttrString(o, "access");
- if (func == NULL) {
- return NULL;
- }
- if (!PyCallable_Check(func)) {
- PyErr_SetString(PyExc_TypeError, "must be callable");
- return NULL;
- }
- set_access_logger(func);
- is_write_access_log = 1;
- Py_RETURN_NONE;
- }
- static PyObject *
- meinheld_error_log(PyObject *self, PyObject *args)
- {
- PyObject *o = NULL;
- PyObject *func = NULL;
- if (!PyArg_ParseTuple(args, "O:error_logger", &o)) {
- return NULL;
- }
- if (o == Py_None) {
- set_err_logger(NULL);
- Py_RETURN_NONE;
- }
- func = PyObject_GetAttrString(o, "error");
- if (func == NULL) {
- return NULL;
- }
- if (!PyCallable_Check(func)) {
- PyErr_SetString(PyExc_TypeError, "must be callable");
- return NULL;
- }
- set_err_logger(func);
- Py_RETURN_NONE;
- }
- static PyObject *
- meinheld_stop(PyObject *self, PyObject *args, PyObject *kwds)
- {
- int timeout = 0;
- static char *kwlist[] = {"timeout", 0};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:timeout",
- kwlist, &timeout)) {
- return NULL;
- }
- kill_server(timeout);
- Py_RETURN_NONE;
- }
- static inline int
- fire_pendings(void)
- {
- int ret = 1;
- TimerObject *timer = NULL;
- pending_queue_t *pendings = g_pendings;
- while(pendings->size && loop_done && activecnt > 0) {
- timer = *(pendings->q + --pendings->size);
- DEBUG("start timer:%p activecnt:%d", timer, activecnt);
- fire_timer(timer);
- Py_DECREF(timer);
- activecnt--;
- DEBUG("fin timer:%p activecnt:%d", timer, activecnt);
- if (PyErr_Occurred()) {
- RDEBUG("pending call raise exception");
- call_error_logger();
- ret = -1;
- break;
- }
- }
- return ret;
- }
- static inline int
- fire_timers(void)
- {
- TimerObject *timer;
- int ret = 1;
- heapq_t *q = g_timers;
- time_t now = current_msec / 1000;
- while(q->size > 0 && loop_done && activecnt > 0) {
- timer = q->heap[0];
- DEBUG("seconds:%d", timer->seconds);
- DEBUG("now:%d", now);
- if (timer->seconds <= now) {
- //call
- timer = heappop(q);
- fire_timer(timer);
- Py_DECREF(timer);
- activecnt--;
- DEBUG("fin timer:%p activecnt:%d", timer, activecnt);
- if (PyErr_Occurred()) {
- RDEBUG("scheduled call raise exception");
- call_error_logger();
- ret = -1;
- break;
- }
- /* timer = q->heap[0]; */
- } else {
- break;
- }
- }
- return ret;
- }
- static int
- listen_all_sockets(void)
- {
- PyObject *iter = NULL, *item = NULL;
- int listen_sock = 0;
- int ret = 0;
- iter = PyObject_GetIter(listen_socks);
- if (PyErr_Occurred()){
- call_error_logger();
- return -1;
- }
- DEBUG("socks iter %p", iter);
- DEBUG("socks size %d", PyList_Size(listen_socks));
- while((item = PyIter_Next(iter))){
- #ifdef PY3
- if (PyLong_Check(item)) {
- listen_sock = (int)PyLong_AsLong(item);
- #else
- if (PyInt_Check(item)) {
- listen_sock = (int)PyInt_AsLong(item);
- #endif
- setup_listen_sock(listen_sock);
- ret = picoev_add(main_loop, listen_sock, PICOEV_READ, ACCEPT_TIMEOUT_SECS, accept_callback, NULL);
- if (ret == 0) {
- activecnt++;
- }
- }
- Py_DECREF(item);
- }
- Py_DECREF(iter);
- return 1;
- }
- static int
- close_all_sockets(void)
- {
- PyObject *iter = NULL, *item = NULL;
- int listen_sock = 0;
- iter = PyObject_GetIter(listen_socks);
- if (PyErr_Occurred()){
- call_error_logger();
- return -1;
- }
- while((item = PyIter_Next(iter))){
- #ifdef PY3
- if (PyLong_Check(item)) {
- listen_sock = (int)PyLong_AsLong(item);
- #else
- if (PyInt_Check(item)) {
- listen_sock = (int)PyInt_AsLong(item);
- #endif
- close(listen_sock);
- if (unix_sock_name) {
- unlink(unix_sock_name);
- unix_sock_name = NULL;
- }
- }
- Py_DECREF(item);
- }
- Py_DECREF(iter);
- return 1;
- }
- static PyObject *
- meinheld_run_loop(PyObject *self, PyObject *args, PyObject *kwds)
- {
- PyObject *watchdog_result;
- int silent = 0;
- int interrupted = 0;
- static char *kwlist[] = {"app", "silent", 0};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i:run",
- kwlist, &wsgi_app, &silent)) {
- return NULL;
- }
- if (listen_socks == NULL) {
- PyErr_Format(PyExc_TypeError, "not found listen socket");
- return NULL;
- }
- Py_INCREF(wsgi_app);
- setup_server_env();
- init_main_loop();
- loop_done = 1;
- PyOS_setsig(SIGPIPE, sigpipe_cb);
- PyOS_setsig(SIGINT, sigint_cb);
- PyOS_setsig(SIGTERM, sigint_cb);
- if (listen_all_sockets() < 0) {
- //FATAL Error
- return NULL;
- }
- /* loop */
- while (likely(loop_done == 1 && activecnt > 0)) {
- /* DEBUG("before activecnt:%d", activecnt); */
- fire_pendings();
- fire_timers();
- picoev_loop_once(main_loop, 10);
- if (unlikely(catch_signal != 0)) {
- if (catch_signal == SIGINT) {
- interrupted = 1;
- }
- catch_signal = 0;
- kill_server(0);
- }
- if (watch_loop && watchdog_lasttime != main_loop->now) {
- watchdog_lasttime = main_loop->now;
- if (tempfile_fd) {
- fast_notify();
- } else if (watchdog) {
- watchdog_result = PyObject_CallFunction(watchdog, NULL);
- if (PyErr_Occurred()) {
- PyErr_Print();
- PyErr_Clear();
- }
- Py_XDECREF(watchdog_result);
- }
- }
- /* DEBUG("after activecnt:%d", activecnt); */
- /* DEBUG("pendings->size:%d", g_pendings->size); */
- }
- Py_DECREF(wsgi_app);
- Py_CLEAR(watchdog);
- current_client = NULL;
- picoev_destroy_loop(main_loop);
- picoev_deinit();
- main_loop = NULL;
- clear_server_env();
- if (close_all_sockets() < 0) {
- Py_CLEAR(listen_socks);
- return NULL;
- }
- Py_CLEAR(listen_socks);
- if (!silent && interrupted) {
- //override
- PyErr_Clear();
- PyErr_SetNone(PyExc_KeyboardInterrupt);
- return NULL;
- }
- Py_RETURN_NONE;
- }
- PyObject *
- meinheld_set_keepalive(PyObject *self, PyObject *args)
- {
- int on;
- if (!PyArg_ParseTuple(args, "i", &on))
- return NULL;
- if (on < 0) {
- PyErr_SetString(PyExc_ValueError, "keep alive value out of range ");
- return NULL;
- }
- is_keep_alive = on;
- if (is_keep_alive) {
- keep_alive_timeout = on;
- } else {
- keep_alive_timeout = 2;
- }
- Py_RETURN_NONE;
- }
- PyObject *
- meinheld_get_keepalive(PyObject *self, PyObject *args)
- {
- return Py_BuildValue("i", is_keep_alive);
- }
- PyObject *
- meinheld_set_backlog(PyObject *self, PyObject *args)
- {
- int temp;
- if (!PyArg_ParseTuple(args, "i", &temp))
- return NULL;
- if (temp <= 0) {
- PyErr_SetString(PyExc_ValueError, "backlog value out of range ");
- return NULL;
- }
- backlog = temp;
- Py_RETURN_NONE;
- }
- PyObject *
- meinheld_get_backlog(PyObject *self, PyObject *args)
- {
- return Py_BuildValue("i", backlog);
- }
- PyObject *
- meinheld_set_picoev_max_fd(PyObject *self, PyObject *args)
- {
- int temp;
- if (!PyArg_ParseTuple(args, "i", &temp))
- return NULL;
- if (temp <= 0) {
- PyErr_SetString(PyExc_ValueError, "max_fd value out of range ");
- return NULL;
- }
- max_fd = temp;
- Py_RETURN_NONE;
- }
- PyObject *
- meinheld_get_picoev_max_fd(PyObject *self, PyObject *args)
- {
- return Py_BuildValue("i", max_fd);
- }
- PyObject *
- meinheld_set_max_content_length(PyObject *self, PyObject *args)
- {
- int temp;
- if (!PyArg_ParseTuple(args, "i", &temp))
- return NULL;
- if (temp <= 0) {
- PyErr_SetString(PyExc_ValueError, "max_content_length value out of range ");
- return NULL;
- }
- max_content_length = temp;
- Py…
Large files files are truncated, but you can click here to view the full file