1 #include "uwsgi.h"
2 
3 extern struct uwsgi_server uwsgi;
4 
threaded_current_wsgi_req()5 struct wsgi_request *threaded_current_wsgi_req() {
6 	return pthread_getspecific(uwsgi.tur_key);
7 }
simple_current_wsgi_req()8 struct wsgi_request *simple_current_wsgi_req() {
9 	return uwsgi.wsgi_req;
10 }
11 
12 
uwsgi_register_loop(char * name,void (* func)(void))13 void uwsgi_register_loop(char *name, void (*func) (void)) {
14 
15 	struct uwsgi_loop *old_loop = NULL, *loop = uwsgi.loops;
16 
17 	while (loop) {
18 		// check if the loop engine is already registered
19 		if (!strcmp(name, loop->name))
20 			return;
21 		old_loop = loop;
22 		loop = loop->next;
23 	}
24 
25 	loop = uwsgi_calloc(sizeof(struct uwsgi_loop));
26 	loop->name = name;
27 	loop->loop = func;
28 
29 	if (old_loop) {
30 		old_loop->next = loop;
31 	}
32 	else {
33 		uwsgi.loops = loop;
34 	}
35 }
36 
uwsgi_get_loop(char * name)37 void *uwsgi_get_loop(char *name) {
38 
39 	struct uwsgi_loop *loop = uwsgi.loops;
40 
41 	while (loop) {
42 		if (!strcmp(name, loop->name)) {
43 			return loop->loop;
44 		}
45 		loop = loop->next;
46 	}
47 	return NULL;
48 }
49 
50 /*
51 
52 	this is the default (simple) loop.
53 
54 	it will run simple_loop_run function for each spawned thread
55 
56 	simple_loop_run monitors sockets and signals descriptors
57 	and manages them.
58 
59 */
60 
simple_loop()61 void simple_loop() {
62 	uwsgi_loop_cores_run(simple_loop_run);
63 	if (uwsgi.workers[uwsgi.mywid].shutdown_sockets)
64 		uwsgi_shutdown_all_sockets();
65 }
66 
uwsgi_loop_cores_run(void * (* func)(void *))67 void uwsgi_loop_cores_run(void *(*func) (void *)) {
68 	int i;
69 	for (i = 1; i < uwsgi.threads; i++) {
70 		long j = i;
71 		pthread_create(&uwsgi.workers[uwsgi.mywid].cores[i].thread_id, &uwsgi.threads_attr, func, (void *) j);
72 	}
73 	long y = 0;
74 	func((void *) y);
75 }
76 
uwsgi_setup_thread_req(long core_id,struct wsgi_request * wsgi_req)77 void uwsgi_setup_thread_req(long core_id, struct wsgi_request *wsgi_req) {
78 	int i;
79 	sigset_t smask;
80 
81 
82 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &i);
83 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &i);
84 	pthread_setspecific(uwsgi.tur_key, (void *) wsgi_req);
85 
86 	if (core_id > 0) {
87 		// block all signals on new threads
88 		sigfillset(&smask);
89 #ifdef UWSGI_DEBUG
90 		sigdelset(&smask, SIGSEGV);
91 #endif
92 		pthread_sigmask(SIG_BLOCK, &smask, NULL);
93 
94 		// run per-thread socket hook
95 		struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
96 		while (uwsgi_sock) {
97 			if (uwsgi_sock->proto_thread_fixup) {
98 				uwsgi_sock->proto_thread_fixup(uwsgi_sock, core_id);
99 			}
100 			uwsgi_sock = uwsgi_sock->next;
101 		}
102 
103 		for (i = 0; i < 256; i++) {
104 			if (uwsgi.p[i]->init_thread) {
105 				uwsgi.p[i]->init_thread(core_id);
106 			}
107 		}
108 	}
109 
110 }
111 
simple_loop_run_int(int core_id)112 void simple_loop_run_int(int core_id) {
113 	long y = core_id;
114 	simple_loop_run((void *) y);
115 }
116 
simple_loop_run(void * arg1)117 void *simple_loop_run(void *arg1) {
118 
119 	long core_id = (long) arg1;
120 
121 	struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
122 
123 	if (uwsgi.threads > 1) {
124 		uwsgi_setup_thread_req(core_id, wsgi_req);
125 	}
126 	// initialize the main event queue to monitor sockets
127 	int main_queue = event_queue_init();
128 
129 	uwsgi_add_sockets_to_queue(main_queue, core_id);
130 
131 	if (uwsgi.signal_socket > -1) {
132 		event_queue_add_fd_read(main_queue, uwsgi.signal_socket);
133 		event_queue_add_fd_read(main_queue, uwsgi.my_signal_socket);
134 	}
135 
136 
137 	// ok we are ready, let's start managing requests and signals
138 	while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
139 
140 		wsgi_req_setup(wsgi_req, core_id, NULL);
141 
142 		if (wsgi_req_accept(main_queue, wsgi_req)) {
143 			continue;
144 		}
145 
146 		if (wsgi_req_recv(main_queue, wsgi_req)) {
147 			uwsgi_destroy_request(wsgi_req);
148 			continue;
149 		}
150 
151 		uwsgi_close_request(wsgi_req);
152 	}
153 
154 	// end of the loop
155 	if (uwsgi.workers[uwsgi.mywid].destroy && uwsgi.workers[0].pid > 0) {
156 #ifdef __APPLE__
157 		kill(uwsgi.workers[0].pid, SIGTERM);
158 #else
159 		if (uwsgi.propagate_touch) {
160 			kill(uwsgi.workers[0].pid, SIGHUP);
161 		}
162 		else {
163 			gracefully_kill(0);
164 		}
165 #endif
166 	}
167 	return NULL;
168 }
169