Ejemplo n.º 1
0
void pc_channel_desire_write(pc_channel_t *channel)
{
    int events;

    channel->desire_write = TRUE;

    events = EV_WRITE;
    if (channel->desire_read)
        events |= EV_READ;

    start_watcher(channel->ctx->cctx->loop, &channel->watcher, events);
}
Ejemplo n.º 2
0
static void
channel_is_usable(struct ev_loop *loop, ev_io *watcher, int revents)
{
    pc_channel_t *channel = watcher->data;
    pc_bool_t dirty = FALSE;

    /* Note that we double-check the callbacks. We want to ignore
       spurious signals to read or write, and then we want to try
       to disable those events (again).  */

    if ((revents & EV_READ) != 0)
    {
        if (channel->desire_read)
            dirty = perform_read(channel);
        else
            dirty = TRUE;
    }
    if ((revents & EV_WRITE) != 0)
    {
        if (channel->desire_write)
            dirty |= perform_write(channel);
        else
            dirty = TRUE;
    }

    /* Do we need to adjust what events we're looking for?  */
    if (dirty)
    {
        int events = 0;

        if (channel->desire_read)
            events |= EV_READ;
        if (channel->desire_write)
            events |= EV_WRITE;

        start_watcher(loop, watcher, events);
    }
}
Ejemplo n.º 3
0
static void gevent_loop() {

	// ensure SIGPIPE is ignored
	signal(SIGPIPE, SIG_IGN);

	if (!uwsgi.has_threads && uwsgi.mywid == 1) {
		uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
	}

	if (uwsgi.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;
	uwsgi.wait_milliseconds_hook = uwsgi_gevent_wait_milliseconds_hook;

	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;

	if (uwsgi.async < 1) {
		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);
	}

	// call gevent.monkey.patch_all() if requested
	if (ugevent.monkey) {
		monkey_patch();
	}

	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)
	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
		start_watcher(i, 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);

	// map SIGINT/SIGTERM with gevent.signal
	ge_signal_tuple = PyTuple_New(2);
	PyTuple_SetItem(ge_signal_tuple, 0, PyInt_FromLong(SIGINT));
	PyObject *uwsgi_gevent_unix_signal_int_handler = PyCFunction_New(uwsgi_gevent_unix_signal_int_handler_def, NULL);
        Py_INCREF(uwsgi_gevent_unix_signal_int_handler);
	PyTuple_SetItem(ge_signal_tuple, 1, uwsgi_gevent_unix_signal_int_handler);
	python_call(ugevent.signal, ge_signal_tuple, 0, NULL);

	ge_signal_tuple = PyTuple_New(2);
	PyTuple_SetItem(ge_signal_tuple, 0, PyInt_FromLong(SIGTERM));
	PyTuple_SetItem(ge_signal_tuple, 1, uwsgi_gevent_unix_signal_int_handler);
	python_call(ugevent.signal, ge_signal_tuple, 0, NULL);




	PyObject *wait_for_me = ugevent.hub;

	if (!ugevent.wait_for_hub) {
		// spawn the control greenlet
		PyObject *uwsgi_greenlet_ctrl_gl_handler = PyCFunction_New(uwsgi_gevent_ctrl_gl_def, NULL);
                Py_INCREF(uwsgi_greenlet_ctrl_gl_handler);
		PyObject *ctrl_gl_args = PyTuple_New(1);
                PyTuple_SetItem(ctrl_gl_args, 0, uwsgi_greenlet_ctrl_gl_handler);
        	ugevent.ctrl_gl = python_call(ugevent.spawn, ctrl_gl_args, 0, NULL);
		Py_INCREF(ugevent.ctrl_gl);
		wait_for_me = ugevent.ctrl_gl;
	}

	for(;;) {
		if (!PyObject_CallMethod(wait_for_me, "join", NULL)) {
			PyErr_Print();
		}
		else {
			break;
		}
	}

	// 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);
                }
        }

	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");

}
Ejemplo n.º 4
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;

}
Ejemplo n.º 5
0
int main(int argc, char **argv)
{
	int i;
	int fanotify_fd, ret;
	struct backend *be = NULL;
	struct stat stbuf;

	logfd = stdout;
	memset(frontend_prefix, 0x0, FILENAME_MAX);

	while ((i = getopt(argc, argv, "b:c:d:m:n:o:p:su:")) != -1) {
		switch (i) {
		case 'b':
			be = new_backend(optarg);
			if (!be) {
				err("Invalid backend '%s'\n", optarg);
				return EINVAL;
			}
			break;
		case 'd':
			if (stat(optarg, &stbuf) < 0 ||
			    !S_ISDIR(stbuf.st_mode)) {
				err("Frontend prefix %s is not a directory",
				    optarg);
				return EINVAL;
			}
			strncpy(frontend_prefix, optarg, FILENAME_MAX);
			break;
		case 'c':
			return cli_command(CLI_CHECK, optarg);
			break;
		case 'm':
			ret = cli_command(CLI_CHECK, optarg);
			if (ret)
				return ret;
			ret = cli_command(CLI_MIGRATE, optarg);
			if (ret)
				return ret;
			/* Fallthrough */
		case 'n':
			return cli_command(CLI_MONITOR, optarg);
			break;
		case 'o':
			if (!be) {
				err("No backend selected");
				return EINVAL;
			}
			if (parse_backend_options(be, optarg) < 0) {
				err("Invalid backend option '%s'", optarg);
				return EINVAL;
			}
			break;
		case 'p':
			log_priority = strtoul(optarg, NULL, 10);
			if (log_priority > LOG_DEBUG) {
				err("Invalid logging priority %d (max %d)",
				    log_priority, LOG_DEBUG);
				exit(1);
			}
			break;
		case 's':
			return cli_command(CLI_SHUTDOWN, NULL);
			break;
		case 'u':
			ret = cli_command(CLI_CHECK, optarg);
			if (ret && ret != ENOENT)
				return ret;
			ret = cli_command(CLI_SETUP, optarg);
			if (ret)
				return ret;
			return cli_command(CLI_MONITOR, optarg);
			break;
		default:
			fprintf(stderr, "usage: %s [-d <dir>]\n", argv[0]);
			return EINVAL;
		}
	}
	if (optind < argc) {
		fprintf(stderr, "usage: %s [-b file] [-p <dir>]\n", argv[0]);
		return EINVAL;
	}

	signal_set(SIGINT, sigend);
	signal_set(SIGTERM, sigend);

	fanotify_fd = fanotify_init(FAN_CLASS_PRE_CONTENT, O_RDWR);
	if (fanotify_fd < 0) {
		fprintf(stderr, "cannot start fanotify, error %d\n",
			errno);
		return errno;
	}

	daemon_thr = pthread_self();

	watcher_thr = start_watcher(be, fanotify_fd);
	if (!watcher_thr)
		return errno;

	cli_thr = start_cli(be, fanotify_fd);
	if (!cli_thr) {
		stop_watcher(watcher_thr);
		return ENOMEM;
	}

	pthread_cond_wait(&exit_cond, &exit_mutex);

	stop_cli(cli_thr);
	stop_watcher(watcher_thr);

	return 0;
}