Пример #1
0
PyObject *py_uwsgi_stackless_worker(PyObject * self, PyObject * args) {

	PyThreadState *ts = PyThreadState_GET();
        struct wsgi_request *wsgi_req = find_request_by_tasklet(ts->st.current);
	PyObject *zero;

	int async_id = wsgi_req->async_id;

	//fprintf(stderr,"i am the tasklet worker\n");

	for(;;) {

		// wait for request
		zero = PyChannel_Receive(uwsgi.workers_channel);

		wsgi_req_setup(wsgi_req, async_id);
		
                if (wsgi_req_accept(uwsgi.serverfd, wsgi_req)) {
                        continue;
                }

		if (wsgi_req_recv(wsgi_req)) {
			continue;
		}

		uwsgi_close_request(&uwsgi, wsgi_req);


	}

}
Пример #2
0
void async_schedule_to_req_green(void) {
	struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
#ifdef UWSGI_ROUTING
        if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
                goto end;
        }
#endif
        for(;;) {
                if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
                        break;
                }
                wsgi_req->switches++;
		if (uwsgi.schedule_fix) {
			uwsgi.schedule_fix(wsgi_req);
		}
                // switch after each yield
                uwsgi.schedule_to_main(wsgi_req);
        }

#ifdef UWSGI_ROUTING
end:
#endif
	// re-set the global state
	uwsgi.wsgi_req = wsgi_req;
        async_reset_request(wsgi_req);
        uwsgi_close_request(wsgi_req);
	// re-set the global state (routing could have changed it)
	uwsgi.wsgi_req = wsgi_req;
        wsgi_req->async_status = UWSGI_OK;
	uwsgi.async_queue_unused_ptr++;
        uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
	
}
Пример #3
0
PyObject *py_uwsgi_tornado_request(PyObject *self, PyObject *args) {
        int fd = -1;
        PyObject *events = NULL;
        if (!PyArg_ParseTuple(args, "iO:uwsgi_tornado_request", &fd, &events)) {
		uwsgi_log_verbose("[BUG] invalid arguments for tornado callback !!!\n");
		exit(1);
        }

        struct wsgi_request *wsgi_req = find_wsgi_req_proto_by_fd(fd);
	uwsgi.wsgi_req = wsgi_req;

	int status = wsgi_req->socket->proto(wsgi_req);
	if (status > 0) goto again;
	if (PyObject_CallMethod(utornado.ioloop, "remove_handler", "i", fd) == NULL) {
		PyErr_Print();
		goto end;
	}

	if (status == 0) {
		// we call this two time... overengineering :(
		uwsgi.async_proto_fd_table[wsgi_req->fd] = NULL;
		uwsgi.schedule_to_req();
		goto again;
	}

end:
	uwsgi.async_proto_fd_table[wsgi_req->fd] = NULL;
	uwsgi_close_request(uwsgi.wsgi_req);	
	free_req_queue;
again:
	Py_INCREF(Py_None);
	return Py_None;
}
Пример #4
0
static PyObject *py_uwsgi_asyncio_request(PyObject *self, PyObject *args) {
        long wsgi_req_ptr = 0;
	int timed_out = 0;
        if (!PyArg_ParseTuple(args, "l|i:uwsgi_asyncio_request", &wsgi_req_ptr, &timed_out)) {
		uwsgi_log_verbose("[BUG] invalid arguments for asyncio callback !!!\n");
		exit(1);
        }

        struct wsgi_request *wsgi_req = (struct wsgi_request *) wsgi_req_ptr;
	uwsgi.wsgi_req = wsgi_req;

	PyObject *ob_timeout = (PyObject *) wsgi_req->async_timeout;
	if (PyObject_CallMethod(ob_timeout, "cancel", NULL) == NULL) PyErr_Print();
	Py_DECREF(ob_timeout);
	// avoid mess when closing the request
	wsgi_req->async_timeout = NULL;

	if (timed_out > 0) {
		if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) PyErr_Print();
		goto end;
	}

	int status = wsgi_req->socket->proto(wsgi_req);
	if (status > 0) {
		ob_timeout = PyObject_CallMethod(uasyncio.loop, "call_later", "iOli", uwsgi.socket_timeout, uasyncio.request, wsgi_req_ptr, 1);
        	if (!ob_timeout) {
                	if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) PyErr_Print();
			goto end;
        	}
                // trick for reference counting
                wsgi_req->async_timeout = (struct uwsgi_rb_timer *) ob_timeout;
		goto again;
	}

	if (PyObject_CallMethod(uasyncio.loop, "remove_reader", "i", wsgi_req->fd) == NULL) {
		PyErr_Print();
		goto end;
	}

	if (status == 0) {
		// we call this two time... overengineering :(
		uwsgi.async_proto_fd_table[wsgi_req->fd] = NULL;
		uwsgi.schedule_to_req();
		goto again;
	}

end:
	uwsgi.async_proto_fd_table[wsgi_req->fd] = NULL;
	uwsgi_close_request(uwsgi.wsgi_req);	
	free_req_queue;
again:
	Py_INCREF(Py_None);
	return Py_None;
}
Пример #5
0
void *simple_loop_run(void *arg1) {

	long core_id = (long) arg1;

	struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;

	if (uwsgi.threads > 1) {
		uwsgi_setup_thread_req(core_id, wsgi_req);
	}
	// initialize the main event queue to monitor sockets
	int main_queue = event_queue_init();

	uwsgi_add_sockets_to_queue(main_queue, core_id);

	if (uwsgi.signal_socket > -1) {
		event_queue_add_fd_read(main_queue, uwsgi.signal_socket);
		event_queue_add_fd_read(main_queue, uwsgi.my_signal_socket);
	}


	// ok we are ready, let's start managing requests and signals
	while (uwsgi.workers[uwsgi.mywid].manage_next_request) {

		wsgi_req_setup(wsgi_req, core_id, NULL);

		if (wsgi_req_accept(main_queue, wsgi_req)) {
			continue;
		}

		if (wsgi_req_recv(main_queue, wsgi_req)) {
			uwsgi_destroy_request(wsgi_req);
			continue;
		}

		uwsgi_close_request(wsgi_req);
	}

	// end of the loop
	if (uwsgi.workers[uwsgi.mywid].destroy && uwsgi.workers[0].pid > 0) {
#ifdef __APPLE__
		kill(uwsgi.workers[0].pid, SIGTERM);
#else
		if (uwsgi.propagate_touch) {
			kill(uwsgi.workers[0].pid, SIGHUP);
		}
		else {
			gracefully_kill(0);
		}
#endif
	}
	return NULL;
}
Пример #6
0
PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {


	struct wsgi_request *wsgi_req = find_first_available_wsgi_req();

	if (wsgi_req == NULL) {
		uwsgi_log("async queue is full !!!\n");
		goto clear;
	}
	uwsgi.wsgi_req = wsgi_req;

	// fill wsgi_request structure
	wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi.sockets );

	// mark core as used
	uwsgi.core[wsgi_req->async_id]->in_request = 1;

	gettimeofday(&wsgi_req->start_of_request, NULL);

	// enter harakiri mode
        if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
                set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
        }

	// accept the connection
	if (wsgi_req_simple_accept(wsgi_req, uwsgi.sockets->fd)) {
		uwsgi_close_request(wsgi_req);
		free_req_queue;
		goto clear;
	}

	// hack to easily pass wsgi_req pointer to the greenlet
	PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));

	// spawn the request greenlet
	PyObject *new_gl = python_call(ugevent.spawn, ugevent.greenlet_args, 0, NULL);
	Py_DECREF(new_gl);

clear:
	Py_INCREF(Py_None);
	return Py_None;
}
Пример #7
0
void async_schedule_to_req_green(void) {
#ifdef UWSGI_ROUTING
        if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
                goto end;
        }
#endif
        for(;;) {
                if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
                        break;
                }
                uwsgi.wsgi_req->switches++;
                // switch after each yield
                uwsgi.schedule_to_main(uwsgi.wsgi_req);
        }

#ifdef UWSGI_ROUTING
end:
#endif
        async_reset_request(uwsgi.wsgi_req);
        uwsgi_close_request(uwsgi.wsgi_req);
        uwsgi.wsgi_req->async_status = UWSGI_OK;
}
Пример #8
0
void async_schedule_to_req(void) {
#ifdef UWSGI_ROUTING
        if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
		goto end;
        }
	// a trick to avoid calling routes again
	uwsgi.wsgi_req->is_routing = 1;
#endif
        if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
		goto end;
	}

	if (uwsgi.schedule_to_main) {
        	uwsgi.schedule_to_main(uwsgi.wsgi_req);
	}
	return;

end:
	async_reset_request(uwsgi.wsgi_req);
	uwsgi_close_request(uwsgi.wsgi_req);
	uwsgi.wsgi_req->async_status = UWSGI_OK;	
}
Пример #9
0
static VALUE uwsgi_rb_thread_core(void *arg) {
	long core_id = (long) arg;
	struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;

        uwsgi_setup_thread_req(core_id, wsgi_req);

	struct uwsgi_rbthread *urbt = uwsgi_malloc(sizeof(struct uwsgi_rbthread));
        // initialize the main event queue to monitor sockets
        urbt->queue = event_queue_init();
	urbt->wsgi_req = wsgi_req;

        uwsgi_add_sockets_to_queue(urbt->queue, (int)core_id);

        if (uwsgi.signal_socket > -1) {
                event_queue_add_fd_read(urbt->queue, uwsgi.signal_socket);
                event_queue_add_fd_read(urbt->queue, uwsgi.my_signal_socket);
        }

        // ok we are ready, let's start managing requests and signals
        while (uwsgi.workers[uwsgi.mywid].manage_next_request) {

                wsgi_req_setup(wsgi_req, (int)core_id, NULL);

		rb_thread_call_without_gvl(uwsgi_rb_thread_accept, urbt, NULL, NULL);
		// accept failed ?
		if (urbt->ret) continue;

                if (wsgi_req_recv(urbt->queue, wsgi_req)) {
                        uwsgi_destroy_request(wsgi_req);
                        continue;
                }

                uwsgi_close_request(wsgi_req);
        }

	return Qnil;
}
Пример #10
0
void *async_loop(void *arg1) {

	struct uwsgi_async_fd *tmp_uaf;
	int interesting_fd, i;
	struct uwsgi_rb_timer *min_timeout;
	int timeout;
	int is_a_new_connection;
	int proto_parser_status;

	time_t now, last_now = 0;

	static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;

	void *events = event_queue_alloc(64);
	struct uwsgi_socket *uwsgi_sock;

	uwsgi.async_runqueue = NULL;
	uwsgi.async_runqueue_cnt = 0;

	if (uwsgi.signal_socket > -1) {
		event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
		event_queue_add_fd_read(uwsgi.async_queue, uwsgi.my_signal_socket);
	}

	// set a default request manager
        if (!uwsgi.schedule_to_req) uwsgi.schedule_to_req = async_schedule_to_req;

	while (uwsgi.workers[uwsgi.mywid].manage_next_request) {

		if (uwsgi.async_runqueue_cnt) {
			timeout = 0;
		}
		else {
			min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
			if (uwsgi.async_runqueue_cnt) {
                        	timeout = 0;
			}
                	if (min_timeout) {
                        	timeout = min_timeout->key - time(NULL);
                        	if (timeout <= 0) {
                                	async_expire_timeouts();
                                	timeout = 0;
                        	}
			}
			else {
				timeout = -1;
			}
                }

		uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);

		// timeout ???
		if (uwsgi.async_nevents == 0) {
                	async_expire_timeouts();
		}


		for(i=0;i<uwsgi.async_nevents;i++) {
			// manage events
			interesting_fd = event_queue_interesting_fd(events, i);

			if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
				uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
				continue;
			}

			is_a_new_connection = 0;

			// new request coming in ?

			uwsgi_sock = uwsgi.sockets;
			while(uwsgi_sock) {

				if (interesting_fd == uwsgi_sock->fd) {

					is_a_new_connection = 1;	

					uwsgi.wsgi_req = find_first_available_wsgi_req();
					if (uwsgi.wsgi_req == NULL) {
						now = time(NULL);
						if (now > last_now) {
							uwsgi_log("async queue is full !!!\n");
							last_now = now;
						}
						break;
					}

					wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock );
					if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
#ifdef UWSGI_EVENT_USE_PORT
                                		event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif
						uwsgi.async_queue_unused_ptr++;
						uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
						break;
					}
#ifdef UWSGI_EVENT_USE_PORT
                                	event_queue_add_fd_read(uwsgi.async_queue, interesting_fd);
#endif

// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
	                                /* re-set blocking socket */
					int arg = uwsgi_sock->arg;
					arg &= (~O_NONBLOCK);
	                                if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, arg) < 0) {
	                                       	uwsgi_error("fcntl()");
						uwsgi.async_queue_unused_ptr++;
						uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
	                                	break;
					}
#endif

					if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
						uwsgi.async_queue_unused_ptr++;
						uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
						break;
					}

					if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
						runqueue_push(uwsgi.wsgi_req);
					}

					break;
				}

				uwsgi_sock = uwsgi_sock->next;
			}

			if (!is_a_new_connection) {
				// proto event
				uwsgi.wsgi_req = find_wsgi_req_proto_by_fd(interesting_fd);
				if (uwsgi.wsgi_req) {
					proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
					// reset timeout
					rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
					free(uwsgi.wsgi_req->async_timeout);
					uwsgi.wsgi_req->async_timeout = NULL;
					// parsing complete
					if (!proto_parser_status) {
						// remove fd from event poll and fd proto table	
#ifndef UWSGI_EVENT_USE_PORT
						event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
#endif
						uwsgi.async_proto_fd_table[interesting_fd] = NULL;
						// put request in the runqueue
						runqueue_push(uwsgi.wsgi_req);
						continue;
					}
					else if (proto_parser_status < 0) {
						if (proto_parser_status == -1)
							uwsgi_log("error parsing request\n");
						uwsgi.async_proto_fd_table[interesting_fd] = NULL;
						close(interesting_fd);
						continue;
					}
					// re-add timer
					async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
					continue;
				}

				// app event
				uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
				// unknown fd, remove it (for safety)
				if (uwsgi.wsgi_req == NULL) {
					close(interesting_fd);
					continue;
				}

				// remove all the fd monitors and timeout
				while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
                                        event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
                                        tmp_uaf = uwsgi.wsgi_req->waiting_fds;
                                        uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
                                        uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
                                        free(tmp_uaf);
                                }
				uwsgi.wsgi_req->waiting_fds = NULL;
                                if (uwsgi.wsgi_req->async_timeout) {
                                        rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
                                        free(uwsgi.wsgi_req->async_timeout);
                                        uwsgi.wsgi_req->async_timeout = NULL;
                                }	

				uwsgi.wsgi_req->async_ready_fd = 1;
				uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;

				// put the request in the runqueue again
				runqueue_push(uwsgi.wsgi_req);
			}
		}

		// event queue managed, give cpu to runqueue
		if (!current_request)
			current_request = uwsgi.async_runqueue;

		if (uwsgi.async_runqueue_cnt) {

			uwsgi.wsgi_req = current_request->wsgi_req;

			uwsgi.schedule_to_req();
			uwsgi.wsgi_req->switches++;

			next_async_request = current_request->next;
			// request ended ?
			if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
				// remove all the monitored fds and timeout
				while(uwsgi.wsgi_req->waiting_fds) {
#ifndef UWSGI_EVENT_USE_PORT
					event_queue_del_fd(uwsgi.async_queue, uwsgi.wsgi_req->waiting_fds->fd, uwsgi.wsgi_req->waiting_fds->event);
#endif
					tmp_uaf = uwsgi.wsgi_req->waiting_fds;
					uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
					uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
					free(tmp_uaf);
				}
				uwsgi.wsgi_req->waiting_fds = NULL;
				if (uwsgi.wsgi_req->async_timeout) {
					rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
                        		free(uwsgi.wsgi_req->async_timeout);
                        		uwsgi.wsgi_req->async_timeout = NULL;
				}

				// remove from the list
				runqueue_remove(current_request);

				uwsgi_close_request(uwsgi.wsgi_req);

				// push wsgi_request in the unused stack
				uwsgi.async_queue_unused_ptr++;
				uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;

			}
			else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
				// remove this request from suspended list	
				runqueue_remove(current_request);
			}

			current_request = next_async_request;

		}


	}

	return NULL;

}
Пример #11
0
PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {

    PyObject *py_wsgi_req = PyTuple_GetItem(args, 0);
    struct wsgi_request *wsgi_req = (struct wsgi_request *) PyLong_AsLong(py_wsgi_req);

    PyObject *greenlet_switch = NULL;

    PyObject *current_greenlet = GET_CURRENT_GREENLET;
    // another hack to retrieve the current wsgi_req;
    PyObject_SetAttrString(current_greenlet, "uwsgi_wsgi_req", py_wsgi_req);

    // if in edge-triggered mode read from socket now !!!
    if (wsgi_req->socket->edge_trigger) {
        int status = wsgi_req->socket->proto(wsgi_req);
        if (status < 0) {
            goto end2;
        }
        goto request;
    }

    greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");

    for(;;) {
        int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
        wsgi_req->switches++;

        if (ret <= 0) {
            goto end;
        }

        int status = wsgi_req->socket->proto(wsgi_req);
        if (status < 0) {
            goto end;
        }
        else if (status == 0) {
            break;
        }
    }

request:

#ifdef UWSGI_ROUTING
    if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
        goto end;
    }
#endif

    for(;;) {
        wsgi_req->async_status = uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req);
        if (wsgi_req->async_status <= UWSGI_OK) {
            goto end;
        }
        wsgi_req->switches++;
        // switch after each yield
        GEVENT_SWITCH;
    }

end:
    Py_DECREF(greenlet_switch);
end2:
    Py_DECREF(current_greenlet);

    uwsgi_close_request(wsgi_req);
    free_req_queue;

    Py_INCREF(Py_None);
    return Py_None;

}
Пример #12
0
PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {

	PyObject *py_wsgi_req = PyTuple_GetItem(args, 0);
	struct wsgi_request *wsgi_req = (struct wsgi_request *) PyLong_AsLong(py_wsgi_req);

	PyObject *greenlet_switch = NULL;

	PyObject *current_greenlet = GET_CURRENT_GREENLET;
	// another hack to retrieve the current wsgi_req;
	PyObject_SetAttrString(current_greenlet, "uwsgi_wsgi_req", py_wsgi_req);

	// if in edge-triggered mode read from socket now !!!
	if (wsgi_req->socket->edge_trigger) {
		int status = wsgi_req->socket->proto(wsgi_req);
		if (status < 0) {
			goto end;
		}
		goto request;
	}

	greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");

	for(;;) {
		int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.socket_timeout);
                wsgi_req->switches++;

                if (ret <= 0) {
                        goto end;
                }

                int status = wsgi_req->socket->proto(wsgi_req);
                if (status < 0) {
                        goto end;
                }
                else if (status == 0) {
                        break;
                }
	}

request:

#ifdef UWSGI_ROUTING
	if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
		goto end;
	}
#endif

	for(;;) {
		if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
			goto end;
		}
		wsgi_req->switches++;
		// switch after each yield
		GEVENT_SWITCH;
	}

end:
	if (greenlet_switch) {
		Py_DECREF(greenlet_switch);
	}

	Py_DECREF(current_greenlet);

	uwsgi_close_request(wsgi_req);
	free_req_queue;


	if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) {
		int running_cores = 0;
		int i;
                for(i=0;i<uwsgi.async;i++) {
                        if (uwsgi.workers[uwsgi.mywid].cores[i].in_request) {
                                running_cores++;
                        }
                }

                if (running_cores == 0) {
                        // no need to worry about freeing memory
                        PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
                        if (uwsgi_dict) {
                                PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
                                if (ae) {
                                        python_call(ae, PyTuple_New(0), 0, NULL);
                                }
                        }
                }
        } else {
                // If we stopped any watcher due to being out of async workers, restart it.
                int i = 0;
                struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
                for (; uwsgi_sock; uwsgi_sock = uwsgi_sock->next, ++i) {
                        PyObject *py_watcher_active = PyObject_GetAttrString(ugevent.watchers[i], "active");
                        if (py_watcher_active && PyBool_Check(py_watcher_active) &&
                            !PyInt_AsLong(py_watcher_active)) {
                            start_watcher(i, uwsgi_sock);
                        }
                        Py_XDECREF(py_watcher_active);
                }
        }

	Py_INCREF(Py_None);
	return Py_None;

}
Пример #13
0
PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {

	PyObject *ret;
	PyObject *py_wsgi_req = PyTuple_GetItem(args, 0);
	struct wsgi_request *wsgi_req = (struct wsgi_request *) PyLong_AsLong(py_wsgi_req);
	int status ;

	PyObject *current_greenlet = GET_CURRENT_GREENLET;
	PyObject *greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");

	uwsgi.wsgi_req = wsgi_req;

	// create a watcher for request socket
	PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
	if (!watcher) goto clear1;

	// a timer to implement timeoit (thanks Denis)
	PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
	if (!timer) goto clear0;

	for(;;) {
		// wait for data in the socket
		PyObject *ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
		if (!ret) goto clear_and_stop;

		// do not forget to overwrite this pointer each time !!!
		uwsgi.wsgi_req = wsgi_req;

		// we can safely decref here as watcher and timer has got a +1 for start() method
		Py_DECREF(ret);
		if (ret == timer) {
			uwsgi_log( "timeout. skip request.\n");
			goto clear_and_stop;
		}
		else if (ret == watcher) {

			status = wsgi_req->socket->proto(wsgi_req);
			if (status < 0) {
				goto clear_and_stop;
			}
			else if (status == 0) {
				stop_the_watchers;
				break;
			}
		}
		else {
			uwsgi_log("unrecognized gevent event !!!\n");
			goto clear_and_stop;
		}

		stop_the_watchers;
	}

	for(;;) {
		uwsgi.wsgi_req = wsgi_req;
		wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
		if (wsgi_req->async_status <= UWSGI_OK) {
			goto clear;
		}
		// switch after each yield
		GEVENT_SWITCH;
	}

	goto clear;

clear_and_stop:

	stop_the_watchers;

clear:
	Py_DECREF(timer);
clear0:
	Py_DECREF(watcher);
clear1:
	Py_DECREF(greenlet_switch);
	Py_DECREF(current_greenlet);
	uwsgi_close_request(wsgi_req);

	uwsgi.wsgi_req = wsgi_req;

	free_req_queue;

	Py_INCREF(Py_None);
	return Py_None;


}
Пример #14
0
void *zeromq_loop(void *arg1) {
	sigset_t smask;
	int i;

	long core_id = (long) arg1;

	struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
	uwsgi.zeromq_recv_flag = 0;
	zmq_pollitem_t zmq_poll_items[3];
	char uwsgi_signal;

	if (uwsgi.threads > 1) {

		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
		pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);

		if (core_id > 0) {
			// block all signals on new threads
			sigfillset(&smask);
			pthread_sigmask(SIG_BLOCK, &smask, NULL);
			for (i = 0; i < 0xFF; i++) {
				if (uwsgi.p[i]->init_thread) {
					uwsgi.p[i]->init_thread(core_id);
				}
			}


			void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
			if (tmp_zmq_pull == NULL) {
				uwsgi_error("zmq_socket()");
				exit(1);
			}
			if (zmq_connect(tmp_zmq_pull, uwsgi.zmq_receiver) < 0) {
				uwsgi_error("zmq_connect()");
				exit(1);
			}

			pthread_setspecific(uwsgi.zmq_pull, tmp_zmq_pull);
		}

	}


	if (uwsgi.signal_socket > -1) {
		zmq_poll_items[0].socket = pthread_getspecific(uwsgi.zmq_pull);
		zmq_poll_items[0].fd = -1;
		zmq_poll_items[0].events = ZMQ_POLLIN;

		zmq_poll_items[1].socket = NULL;
		zmq_poll_items[1].fd = uwsgi.signal_socket;
		zmq_poll_items[1].events = ZMQ_POLLIN;

		zmq_poll_items[2].socket = NULL;
		zmq_poll_items[2].fd = uwsgi.my_signal_socket;
		zmq_poll_items[2].events = ZMQ_POLLIN;
	}


	while (uwsgi.workers[uwsgi.mywid].manage_next_request) {

		wsgi_req_setup(wsgi_req, core_id, NULL);

		uwsgi.edge_triggered = 1;
		wsgi_req->socket = uwsgi.zmq_socket;


		if (uwsgi.signal_socket > -1) {
			if (zmq_poll(zmq_poll_items, 3, -1) < 0) {
				uwsgi_error("zmq_poll()");
				continue;
			}

			if (zmq_poll_items[1].revents & ZMQ_POLLIN) {
                		if (read(uwsgi.signal_socket, &uwsgi_signal, 1) <= 0) {
                        		if (uwsgi.no_orphans) {
                                		uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
                                		end_me(0);
                        		}
                		}
                		else {
#ifdef UWSGI_DEBUG
                        		uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
#endif
                        		if (uwsgi_signal_handler(uwsgi_signal)) {
                                		uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
                        		}
                		}
				continue;
			}

			if (zmq_poll_items[2].revents & ZMQ_POLLIN) {
                                if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) <= 0) {
                                        if (uwsgi.no_orphans) {
                                                uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
                                                end_me(0);
                                        }
                                }
                                else {
#ifdef UWSGI_DEBUG
                                        uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
#endif
                                        if (uwsgi_signal_handler(uwsgi_signal)) {
                                                uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
                                        }
                                }
                                continue;
                        }

			

			if (zmq_poll_items[0].revents & ZMQ_POLLIN) {
				wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
			}
		}
		else {
			wsgi_req->poll.fd = wsgi_req->socket->proto_accept(wsgi_req, uwsgi.zmq_socket->fd);
		}

		if (wsgi_req->poll.fd >= 0) {
			wsgi_req_recv(wsgi_req);
		}

		uwsgi_close_request(wsgi_req);
	}


        // end of the loop
        return NULL;
}
Пример #15
0
PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {

	PyObject *py_wsgi_req = PyTuple_GetItem(args, 0);
	struct wsgi_request *wsgi_req = (struct wsgi_request *) PyLong_AsLong(py_wsgi_req);

	PyObject *greenlet_switch = NULL;

	PyObject *current_greenlet = GET_CURRENT_GREENLET;
	// another hack to retrieve the current wsgi_req;
	PyObject_SetAttrString(current_greenlet, "uwsgi_wsgi_req", py_wsgi_req);

	// if in edge-triggered mode read from socket now !!!
	if (wsgi_req->socket->edge_trigger) {
		int status = wsgi_req->socket->proto(wsgi_req);
		if (status < 0) {
			goto end2;
		}
		goto request;
	}

	greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");

	for(;;) {
		int ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
                wsgi_req->switches++;

                if (ret <= 0) {
                        goto end;
                }

                int status = wsgi_req->socket->proto(wsgi_req);
                if (status < 0) {
                        goto end;
                }
                else if (status == 0) {
                        break;
                }
	}

request:

#ifdef UWSGI_ROUTING
	if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
		goto end;
	}
#endif

	for(;;) {
		if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
			goto end;
		}
		wsgi_req->switches++;
		// switch after each yield
		GEVENT_SWITCH;
	}

end:
	Py_DECREF(greenlet_switch);
end2:
	Py_DECREF(current_greenlet);

	uwsgi_close_request(wsgi_req);
	free_req_queue;


	if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) {
		int running_cores = 0;
		int i;
          for(i=0;i<uwsgi.async;i++) {
            if (uwsgi.workers[uwsgi.mywid].cores[i].in_request) {
              running_cores++;
            }
          }

          if (running_cores == 0) {
            // no need to worry about freeing memory
            PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
            if (uwsgi_dict) {
              PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
              if (ae) {
                python_call(ae, PyTuple_New(0), 0, NULL);
              }
            }
          }
        }

	Py_INCREF(Py_None);
	return Py_None;

}
Пример #16
0
Файл: loop.c Проект: 20tab/uwsgi
void *simple_loop(void *arg1) {

	long core_id = (long) arg1;

	struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];

#ifdef UWSGI_THREADING
	int i;
	sigset_t smask;

	if (uwsgi.threads > 1) {

		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
		pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);

		if (core_id > 0) {
			// block all signals on new threads
			sigfillset(&smask);
#ifdef UWSGI_DEBUG
			sigdelset(&smask, SIGSEGV);
#endif
			pthread_sigmask(SIG_BLOCK, &smask, NULL);

			// run per-thread socket hook
			struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
			while(uwsgi_sock) {
				if (uwsgi_sock->proto_thread_fixup) {
					uwsgi_sock->proto_thread_fixup(uwsgi_sock, core_id);
				}
				uwsgi_sock = uwsgi_sock->next;
			}

			for (i = 0; i < 256; i++) {
				if (uwsgi.p[i]->init_thread) {
					uwsgi.p[i]->init_thread(core_id);
				}
			}
		}
	}
#endif

	// initialize the main event queue to monitor sockets
	int main_queue = event_queue_init();

	uwsgi_add_sockets_to_queue(main_queue, core_id);

	if (uwsgi.signal_socket > -1) {
		event_queue_add_fd_read(main_queue, uwsgi.signal_socket);
		event_queue_add_fd_read(main_queue, uwsgi.my_signal_socket);
	}


	// ok we are ready, let's start managing requests and signals
	while (uwsgi.workers[uwsgi.mywid].manage_next_request) {

		wsgi_req_setup(wsgi_req, core_id, NULL);

		if (wsgi_req_accept(main_queue, wsgi_req)) {
			continue;
		}

		if (wsgi_req_recv(wsgi_req)) {
			uwsgi_destroy_request(wsgi_req);
			continue;
		}

		uwsgi_close_request(wsgi_req);
	}

	// end of the loop
	if (uwsgi.workers[uwsgi.mywid].destroy && uwsgi.workers[0].pid > 0) {
#ifdef __APPLE__
		kill(uwsgi.workers[0].pid, SIGTERM);
#else
		if (uwsgi.propagate_touch) {
			kill(uwsgi.workers[0].pid, SIGHUP);
		}
		else {
			gracefully_kill(0);
		}
#endif
	}
	return NULL;
}
Пример #17
0
void async_loop() {

	if (uwsgi.async < 2) {
		uwsgi_log("the async loop engine requires async mode (--async <n>)\n");
		exit(1);
	}

	struct uwsgi_async_fd *tmp_uaf;
	int interesting_fd, i;
	struct uwsgi_rb_timer *min_timeout;
	int timeout;
	int is_a_new_connection;
	int proto_parser_status;

	uint64_t now;

	static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;

	void *events = event_queue_alloc(64);
	struct uwsgi_socket *uwsgi_sock;

	uwsgi.async_runqueue = NULL;
	uwsgi.async_runqueue_cnt = 0;

	uwsgi.wait_write_hook = async_wait_fd_write;
        uwsgi.wait_read_hook = async_wait_fd_read;

	if (uwsgi.signal_socket > -1) {
		event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
		event_queue_add_fd_read(uwsgi.async_queue, uwsgi.my_signal_socket);
	}

	// set a default request manager
	if (!uwsgi.schedule_to_req)
		uwsgi.schedule_to_req = async_schedule_to_req;

	if (!uwsgi.schedule_to_main) {
		uwsgi_log("*** WARNING *** async mode without coroutine/greenthread engine loaded !!!\n");
	}

	while (uwsgi.workers[uwsgi.mywid].manage_next_request) {

		now = (uint64_t) uwsgi_now();
		if (uwsgi.async_runqueue_cnt) {
			timeout = 0;
		}
		else {
			min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
			if (min_timeout) {
				timeout = min_timeout->value - now;
				if (timeout <= 0) {
					async_expire_timeouts(now);
					timeout = 0;
				}
			}
			else {
				timeout = -1;
			}
		}

		uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);

		now = (uint64_t) uwsgi_now();
		// timeout ???
		if (uwsgi.async_nevents == 0) {
			async_expire_timeouts(now);
		}


		for (i = 0; i < uwsgi.async_nevents; i++) {
			// manage events
			interesting_fd = event_queue_interesting_fd(events, i);

			if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
				uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
				continue;
			}


			is_a_new_connection = 0;

			// new request coming in ?

			uwsgi_sock = uwsgi.sockets;
			while (uwsgi_sock) {

				if (interesting_fd == uwsgi_sock->fd) {

					is_a_new_connection = 1;

					uwsgi.wsgi_req = find_first_available_wsgi_req();
					if (uwsgi.wsgi_req == NULL) {
						uwsgi_async_queue_is_full((time_t)now);
						break;
					}

					wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
					if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
						uwsgi.async_queue_unused_ptr++;
						uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
						break;
					}

					if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
						uwsgi.async_queue_unused_ptr++;
						uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
						break;
					}

					if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
						runqueue_push(uwsgi.wsgi_req);
					}

					break;
				}

				uwsgi_sock = uwsgi_sock->next;
			}

			if (!is_a_new_connection) {
				// proto event
				uwsgi.wsgi_req = find_wsgi_req_proto_by_fd(interesting_fd);
				if (uwsgi.wsgi_req) {
					proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
					// reset timeout
					uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
					free(uwsgi.wsgi_req->async_timeout);
					uwsgi.wsgi_req->async_timeout = NULL;
					// parsing complete
					if (!proto_parser_status) {
						// remove fd from event poll and fd proto table 
						uwsgi.async_proto_fd_table[interesting_fd] = NULL;
						event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
						// put request in the runqueue
						runqueue_push(uwsgi.wsgi_req);
						continue;
					}
					else if (proto_parser_status < 0) {
						if (proto_parser_status == -1)
							uwsgi_log("error parsing request\n");
						uwsgi.async_proto_fd_table[interesting_fd] = NULL;
						close(interesting_fd);
						continue;
					}
					// re-add timer
					async_add_timeout(uwsgi.wsgi_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
					continue;
				}

				// app event
				uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
				// unknown fd, remove it (for safety)
				if (uwsgi.wsgi_req == NULL) {
					close(interesting_fd);
					continue;
				}

				// remove all the fd monitors and timeout
				while (uwsgi.wsgi_req->waiting_fds) {
					tmp_uaf = uwsgi.wsgi_req->waiting_fds;
					uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
					event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
					uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
					free(tmp_uaf);
				}
				uwsgi.wsgi_req->waiting_fds = NULL;
				if (uwsgi.wsgi_req->async_timeout) {
					uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
					free(uwsgi.wsgi_req->async_timeout);
					uwsgi.wsgi_req->async_timeout = NULL;
				}

				uwsgi.wsgi_req->async_ready_fd = 1;
				uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;

				// put the request in the runqueue again
				runqueue_push(uwsgi.wsgi_req);
				// avoid managing other enqueued events...
				break;
			}
		}

		// event queue managed, give cpu to runqueue
		if (!current_request)
			current_request = uwsgi.async_runqueue;

		if (uwsgi.async_runqueue_cnt) {

			uwsgi.wsgi_req = current_request->wsgi_req;

			uwsgi.schedule_to_req();
			uwsgi.wsgi_req->switches++;

			next_async_request = current_request->next;
			// request ended ?
			if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
				// remove all the monitored fds and timeout
				while (uwsgi.wsgi_req->waiting_fds) {
					tmp_uaf = uwsgi.wsgi_req->waiting_fds;
					uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
					event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
					uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
					free(tmp_uaf);
				}
				uwsgi.wsgi_req->waiting_fds = NULL;
				if (uwsgi.wsgi_req->async_timeout) {
					uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
					free(uwsgi.wsgi_req->async_timeout);
					uwsgi.wsgi_req->async_timeout = NULL;
				}

				// remove from the list
				runqueue_remove(current_request);

				uwsgi_close_request(uwsgi.wsgi_req);

				// push wsgi_request in the unused stack
				uwsgi.async_queue_unused_ptr++;
				uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;

			}
			else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
				// remove this request from suspended list      
				runqueue_remove(current_request);
			}

			current_request = next_async_request;

		}


	}

}