PyObject *py_uwsgi_gevent_graceful(PyObject *self, PyObject *args) { uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); uwsgi.workers[uwsgi.mywid].manage_next_request = 0; uwsgi_log_verbose("stopping gevent signals watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); PyObject_CallMethod(ugevent.my_signal_watcher, "stop", NULL); PyObject_CallMethod(ugevent.signal_watcher, "stop", NULL); uwsgi_log_verbose("stopping gevent sockets watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); int i,count = uwsgi_count_sockets(uwsgi.sockets); for(i=0; i<count; i++) { PyObject_CallMethod(ugevent.watchers[i], "stop", NULL); } uwsgi_log_verbose("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); int running_cores = 0; for(i=0; i<uwsgi.async; i++) { if (uwsgi.workers[uwsgi.mywid].cores[i].in_request) { struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[i].req; uwsgi_log_verbose("worker %d (pid: %d) core %d is managing \"%.*s %.*s\" for %.*s\n", uwsgi.mywid, uwsgi.mypid, i, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr); running_cores++; } } if (running_cores > 0) { uwsgi_log_verbose("waiting for %d running requests on worker %d (pid: %d)...\n", running_cores, uwsgi.mywid, uwsgi.mypid); } Py_INCREF(Py_None); return Py_None; }
PyObject *py_uwsgi_gevent_graceful(PyObject *self, PyObject *args) { int running_cores = 0; int rounds = 0; uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); uwsgi.workers[uwsgi.mywid].manage_next_request = 0; uwsgi_log_verbose("stopping gevent signals watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); PyObject_CallMethod(ugevent.my_signal_watcher, "stop", NULL); PyObject_CallMethod(ugevent.signal_watcher, "stop", NULL); uwsgi_log_verbose("stopping gevent sockets watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); int i,count = uwsgi_count_sockets(uwsgi.sockets); for(i=0;i<count;i++) { PyObject_CallMethod(ugevent.watchers[i], "stop", NULL); } uwsgi_log_verbose("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); retry: running_cores = 0; for(i=0;i<uwsgi.async;i++) { if (uwsgi.workers[uwsgi.mywid].cores[i].in_request) { struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[i].req; if (!rounds) { uwsgi_log_verbose("worker %d (pid: %d) core %d is managing \"%.*s %.*s\" for %.*s\n", uwsgi.mywid, uwsgi.mypid, i, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr); } running_cores++; } } if (running_cores > 0) { uwsgi_log_verbose("waiting for %d running requests on worker %d (pid: %d)...\n", running_cores, uwsgi.mywid, uwsgi.mypid); PyObject *gevent_sleep_args = PyTuple_New(1); PyTuple_SetItem(gevent_sleep_args, 0, PyInt_FromLong(1)); PyObject *gswitch = python_call(ugevent.greenlet_switch, gevent_sleep_args, 0, NULL); Py_DECREF(gswitch); Py_DECREF(gevent_sleep_args); rounds++; goto retry; } if (!ugevent.wait_for_hub) { PyObject_CallMethod(ugevent.ctrl_gl, "kill", NULL); } Py_INCREF(Py_None); return Py_None; }
PyObject *py_uwsgi_gevent_graceful(PyObject *self, PyObject *args) { uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); uwsgi.workers[uwsgi.mywid].manage_next_request = 0; uwsgi_log_verbose("stopping gevent signals watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); PyObject_CallMethod(ugevent.my_signal_watcher, "stop", NULL); PyObject_CallMethod(ugevent.signal_watcher, "stop", NULL); uwsgi_log_verbose("stopping gevent sockets watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); int i,count = uwsgi_count_sockets(uwsgi.sockets); for(i=0;i<count;i++) { PyObject_CallMethod(ugevent.watchers[i], "stop", NULL); } uwsgi_log_verbose("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); int running_cores = 0; for(i=0;i<uwsgi.async;i++) { if (uwsgi.workers[uwsgi.mywid].cores[i].in_request) { struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[i].req; uwsgi_log_verbose("worker %d (pid: %d) core %d is managing \"%.*s %.*s\" for %.*s\n", uwsgi.mywid, uwsgi.mypid, i, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr); running_cores++; } } if (running_cores > 0) { uwsgi_log_verbose("waiting for %d running requests on worker %d (pid: %d)...\n", running_cores, uwsgi.mywid, uwsgi.mypid); } else { // 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; }
PyObject *py_uwsgi_gevent_int(PyObject *self, PyObject *args) { uwsgi_log("Brutally killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); uwsgi.workers[uwsgi.mywid].manage_next_request = 0; uwsgi_log_verbose("stopping gevent signals watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); PyObject_CallMethod(ugevent.my_signal_watcher, "stop", NULL); PyObject_CallMethod(ugevent.signal_watcher, "stop", NULL); uwsgi_log_verbose("stopping gevent sockets watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); int i,count = uwsgi_count_sockets(uwsgi.sockets); for(i=0;i<count;i++) { PyObject_CallMethod(ugevent.watchers[i], "stop", NULL); } uwsgi_log_verbose("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); if (!ugevent.wait_for_hub) { PyObject_CallMethod(ugevent.ctrl_gl, "kill", NULL); } Py_INCREF(Py_None); return Py_None; }
PyObject *py_uwsgi_gevent_graceful(PyObject *self, PyObject *args) { uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); uwsgi.workers[uwsgi.mywid].manage_next_request = 0; uwsgi_log("stopping gevent signals watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); PyObject_CallMethod(ugevent.my_signal_watcher, "stop", NULL); PyObject_CallMethod(ugevent.signal_watcher, "stop", NULL); uwsgi_log("stopping gevent sockets watchers for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); int i,count = uwsgi_count_sockets(uwsgi.sockets); for(i=0;i<count;i++) { PyObject_CallMethod(ugevent.watchers[i], "stop", NULL); } uwsgi_log("main gevent watchers stopped for worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid); if (args) { exit(UWSGI_RELOAD_CODE); } Py_INCREF(Py_None); return Py_None; }
static void gevent_loop() { if (!uwsgi.has_threads && uwsgi.mywid == 1) { uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n"); } if (uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] < 30) { uwsgi_log("!!! Running gevent with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n"); } // get the GIL UWSGI_GET_GIL up.gil_get = gil_gevent_get; up.gil_release = gil_gevent_release; uwsgi.wait_write_hook = uwsgi_gevent_wait_write_hook; uwsgi.wait_read_hook = uwsgi_gevent_wait_read_hook; struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; if (uwsgi.async < 2) { uwsgi_log("the gevent loop engine requires async mode (--async <n>)\n"); exit(1); } uwsgi.current_wsgi_req = uwsgi_gevent_current_wsgi_req; PyObject *gevent_dict = get_uwsgi_pydict("gevent"); if (!gevent_dict) uwsgi_pyexit; PyObject *gevent_version = PyDict_GetItemString(gevent_dict, "version_info"); if (!gevent_version) uwsgi_pyexit; if (PyInt_AsLong(PyTuple_GetItem(gevent_version, 0)) < 1) { uwsgi_log("uWSGI requires at least gevent 1.x version\n"); exit(1); } ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn"); if (!ugevent.spawn) uwsgi_pyexit; ugevent.signal = PyDict_GetItemString(gevent_dict, "signal"); if (!ugevent.signal) uwsgi_pyexit; ugevent.greenlet_switch = PyDict_GetItemString(gevent_dict, "sleep"); if (!ugevent.greenlet_switch) uwsgi_pyexit; ugevent.greenlet_switch_args = PyTuple_New(0); Py_INCREF(ugevent.greenlet_switch_args); PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub"); ugevent.hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL); if (!ugevent.hub) uwsgi_pyexit; ugevent.get_current = PyDict_GetItemString(gevent_dict, "getcurrent"); if (!ugevent.get_current) uwsgi_pyexit; ugevent.get_current_args = PyTuple_New(0); Py_INCREF(ugevent.get_current_args); ugevent.hub_loop = PyObject_GetAttrString(ugevent.hub, "loop"); if (!ugevent.hub_loop) uwsgi_pyexit; // main greenlet waiting for connection (one greenlet per-socket) PyObject *uwsgi_gevent_main = PyCFunction_New(uwsgi_gevent_main_def, NULL); Py_INCREF(uwsgi_gevent_main); // greenlet to run at each request PyObject *uwsgi_request_greenlet = PyCFunction_New(uwsgi_gevent_request_def, NULL); Py_INCREF(uwsgi_request_greenlet); // pre-fill the greenlet args ugevent.greenlet_args = PyTuple_New(2); PyTuple_SetItem(ugevent.greenlet_args, 0, uwsgi_request_greenlet); if (uwsgi.signal_socket > -1) { // and these are the watcher for signal sockets ugevent.signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.signal_socket, 1); if (!ugevent.signal_watcher) uwsgi_pyexit; ugevent.my_signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.my_signal_socket, 1); if (!ugevent.my_signal_watcher) uwsgi_pyexit; PyObject *uwsgi_greenlet_signal = PyCFunction_New(uwsgi_gevent_signal_def, NULL); Py_INCREF(uwsgi_greenlet_signal); PyObject *uwsgi_greenlet_my_signal = PyCFunction_New(uwsgi_gevent_my_signal_def, NULL); Py_INCREF(uwsgi_greenlet_my_signal); PyObject *uwsgi_greenlet_signal_handler = PyCFunction_New(uwsgi_gevent_signal_handler_def, NULL); Py_INCREF(uwsgi_greenlet_signal_handler); ugevent.signal_args = PyTuple_New(2); PyTuple_SetItem(ugevent.signal_args, 0, uwsgi_greenlet_signal_handler); // start the two signal watchers if (!PyObject_CallMethod(ugevent.signal_watcher, "start", "O", uwsgi_greenlet_signal)) uwsgi_pyexit; if (!PyObject_CallMethod(ugevent.my_signal_watcher, "start", "O", uwsgi_greenlet_my_signal)) uwsgi_pyexit; } // start a greenlet for each socket ugevent.watchers = uwsgi_malloc(sizeof(PyObject *) * uwsgi_count_sockets(uwsgi.sockets)); int i = 0; while(uwsgi_sock) { // this is the watcher for server socket ugevent.watchers[i] = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi_sock->fd, 1); if (!ugevent.watchers[i]) uwsgi_pyexit; // start the main greenlet PyObject_CallMethod(ugevent.watchers[i], "start", "Ol", uwsgi_gevent_main,(long)uwsgi_sock); uwsgi_sock = uwsgi_sock->next; i++; } // patch goodbye_cruel_world uwsgi.gbcw_hook = uwsgi_gevent_gbcw; // map SIGHUP with gevent.signal PyObject *ge_signal_tuple = PyTuple_New(2); PyTuple_SetItem(ge_signal_tuple, 0, PyInt_FromLong(SIGHUP)); PyObject *uwsgi_gevent_unix_signal_handler = PyCFunction_New(uwsgi_gevent_unix_signal_handler_def, NULL); Py_INCREF(uwsgi_gevent_unix_signal_handler); PyTuple_SetItem(ge_signal_tuple, 1, uwsgi_gevent_unix_signal_handler); python_call(ugevent.signal, ge_signal_tuple, 0, NULL); for(;;) { if (!PyObject_CallMethod(ugevent.hub, "join", NULL)) { PyErr_Print(); } else { break; } } if (uwsgi.workers[uwsgi.mywid].manage_next_request == 0) { uwsgi_log("goodbye to the gevent Hub on worker %d (pid: %d)\n", uwsgi.mywid, uwsgi.mypid); if (ugevent.destroy) { exit(0); } exit(UWSGI_RELOAD_CODE); } uwsgi_log("the gevent Hub is no more :(\n"); }
void uwsgi_manage_zerg(int fd, int num_sockets, int *sockets) { struct sockaddr_un zsun; socklen_t zsun_len = sizeof(struct sockaddr_un); int zerg_client = accept(fd, (struct sockaddr *) &zsun, &zsun_len); if (zerg_client < 0) { uwsgi_error("zerg: accept()"); return; } if (!num_sockets) { num_sockets = uwsgi_count_sockets(uwsgi.sockets); } struct msghdr zerg_msg; void *zerg_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_sockets)); struct iovec zerg_iov[2]; struct cmsghdr *cmsg; zerg_iov[0].iov_base = "uwsgi-zerg"; zerg_iov[0].iov_len = 10; zerg_iov[1].iov_base = &num_sockets; zerg_iov[1].iov_len = sizeof(int); zerg_msg.msg_name = NULL; zerg_msg.msg_namelen = 0; zerg_msg.msg_iov = zerg_iov; zerg_msg.msg_iovlen = 2; zerg_msg.msg_flags = 0; zerg_msg.msg_control = zerg_msg_control; zerg_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_sockets); cmsg = CMSG_FIRSTHDR(&zerg_msg); cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_sockets); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; unsigned char *zerg_fd_ptr = CMSG_DATA(cmsg); if (!sockets) { struct uwsgi_socket *uwsgi_sock = uwsgi.sockets; int uniq_count = 0; while (uwsgi_sock) { if (uwsgi_sock->fd == -1) goto nextsock; if (!uwsgi_socket_uniq(uwsgi.sockets, uwsgi_sock)) { memcpy(zerg_fd_ptr, &uwsgi_sock->fd, sizeof(int)); zerg_fd_ptr += sizeof(int); uniq_count++; } nextsock: uwsgi_sock = uwsgi_sock->next; } zerg_iov[1].iov_base = &uniq_count; cmsg->cmsg_len = CMSG_LEN(sizeof(int) * uniq_count); } else { memcpy(zerg_fd_ptr, sockets, sizeof(int) * num_sockets); } if (sendmsg(zerg_client, &zerg_msg, 0) < 0) { uwsgi_error("sendmsg()"); } free(zerg_msg_control); close(zerg_client); }