1 /* select.c
2  * Select Loop
3  * (c) 2002 Mikulas Patocka
4  * This file is a part of the Links program, released under GPL.
5  */
6 
7 #include "links.h"
8 
9 /*
10 #define DEBUG_CALLS
11 */
12 
13 #ifdef USE_LIBEVENT
14 #if defined(evtimer_set) && !defined(timeout_set)
15 #define timeout_set	evtimer_set
16 #endif
17 #if defined(evtimer_add) && !defined(timeout_add)
18 #define timeout_add	evtimer_add
19 #endif
20 #if defined(evtimer_del) && !defined(timeout_del)
21 #define timeout_del	evtimer_del
22 #endif
23 #endif
24 
25 struct thread {
26 	void (*read_func)(void *);
27 	void (*write_func)(void *);
28 	void *data;
29 #ifdef USE_LIBEVENT
30 	struct event *read_event;
31 	struct event *write_event;
32 #endif
33 };
34 
35 static struct thread *threads = DUMMY;
36 static int n_threads = 0;
37 
38 static fd_set w_read;
39 static fd_set w_write;
40 
41 static fd_set x_read;
42 static fd_set x_write;
43 
44 static int w_max;
45 
46 struct timer {
47 	list_entry_1st
48 	uttime interval;
49 	void (*func)(void *);
50 	void *data;
51 	list_entry_last
52 };
53 
54 static struct list_head timers = { &timers, &timers };
55 
56 
57 #if !defined(OS2) && !defined(OPENVMS)
portable_sleep(unsigned msec)58 void portable_sleep(unsigned msec)
59 {
60 	struct timeval tv;
61 	int rs;
62 	block_signals(0, 0);
63 	tv.tv_sec = msec / 1000;
64 	tv.tv_usec = msec % 1000 * 1000;
65 	EINTRLOOP(rs, select(0, NULL, NULL, NULL, &tv));
66 	unblock_signals();
67 }
68 #endif
69 
can_do_io(int fd,int wr,int sec)70 static int can_do_io(int fd, int wr, int sec)
71 {
72 	fd_set fds;
73 	struct timeval tv, *tvp;
74 	int rs;
75 
76 	if (fd < 0)
77 		internal_error("can_do_io: handle %d", fd);
78 
79 #if defined(USE_POLL)
80 	{
81 		struct pollfd p;
82 		p.fd = fd;
83 		p.events = !wr ? POLLIN : POLLOUT;
84 		EINTRLOOP(rs, poll(&p, 1, sec < 0 ? -1 : sec * 1000));
85 		if (rs < 0) fatal_exit("ERROR: poll for %s (%d) failed: %s", !wr ? "read" : "write", fd, strerror(errno));
86 		if (!rs) return 0;
87 		if (p.revents & POLLNVAL) goto fallback;
88 		return 1;
89 	}
90 fallback:
91 #endif
92 	if (sec >= 0) {
93 		tv.tv_sec = sec;
94 		tv.tv_usec = 0;
95 		tvp = &tv;
96 	} else {
97 		tvp = NULL;
98 	}
99 	FD_ZERO(&fds);
100 	if (fd >= (int)FD_SETSIZE) {
101 		fatal_exit("too big handle %d", fd);
102 	}
103 	FD_SET(fd, &fds);
104 	if (!wr)
105 		EINTRLOOP(rs, select(fd + 1, &fds, NULL, NULL, tvp));
106 	else
107 		EINTRLOOP(rs, select(fd + 1, NULL, &fds, NULL, tvp));
108 	if (rs < 0) fatal_exit("ERROR: select for %s (%d) failed: %s", !wr ? "read" : "write", fd, strerror(errno));
109 	return rs;
110 }
111 
can_write(int fd)112 int can_write(int fd)
113 {
114 	return can_do_io(fd, 1, 0);
115 }
116 
can_read_timeout(int fd,int sec)117 int can_read_timeout(int fd, int sec)
118 {
119 	return can_do_io(fd, 0, sec);
120 }
121 
can_read(int fd)122 int can_read(int fd)
123 {
124 	return can_do_io(fd, 0, 0);
125 }
126 
127 
close_std_handle(int std)128 int close_std_handle(int std)
129 {
130 #ifndef DOS
131 	int n, h, rs;
132 	if (std == 1)
133 		fflush(stdout);
134 	if (std == 2)
135 		fflush(stderr);
136 	n = c_open(cast_uchar "/dev/null", O_WRONLY | O_NOCTTY);
137 	if (n == -1)
138 		goto fail1;
139 	h = c_dup(std);
140 	if (h == -1)
141 		goto fail2;
142 	EINTRLOOP(rs, dup2(n, std));
143 	if (rs == -1)
144 		goto fail3;
145 	EINTRLOOP(rs, close(n));
146 	return h;
147 
148 fail3:
149 	EINTRLOOP(rs, close(h));
150 fail2:
151 	EINTRLOOP(rs, close(n));
152 fail1:
153 #endif
154 	return -1;
155 }
156 
restore_std_handle(int std,int h)157 void restore_std_handle(int std, int h)
158 {
159 #ifndef DOS
160 	int rs;
161 	if (std == 1)
162 		fflush(stdout);
163 	if (std == 2)
164 		fflush(stderr);
165 	if (h == -1)
166 		return;
167 	EINTRLOOP(rs, dup2(h, std));
168 	EINTRLOOP(rs, close(h));
169 #endif
170 }
171 
172 
select_info(int type)173 unsigned long select_info(int type)
174 {
175 	int i, j;
176 	switch (type) {
177 		case CI_FILES:
178 			i = 0;
179 			for (j = 0; j < w_max; j++)
180 				if (threads[j].read_func || threads[j].write_func) i++;
181 			return i;
182 		case CI_TIMERS:
183 			return list_size(&timers);
184 		default:
185 			internal_error("select_info_info: bad request");
186 	}
187 	return 0;
188 }
189 
190 struct bottom_half {
191 	list_entry_1st
192 	void (*fn)(void *);
193 	void *data;
194 	list_entry_last
195 };
196 
197 static struct list_head bottom_halves = { &bottom_halves, &bottom_halves };
198 
register_bottom_half(void (* fn)(void *),void * data)199 void register_bottom_half(void (*fn)(void *), void *data)
200 {
201 	struct bottom_half *bh;
202 	struct list_head *lbh;
203 	foreach(struct bottom_half, bh, lbh, bottom_halves) if (bh->fn == fn && bh->data == data) return;
204 	bh = mem_alloc(sizeof(struct bottom_half));
205 	bh->fn = fn;
206 	bh->data = data;
207 	add_to_list(bottom_halves, bh);
208 }
209 
unregister_bottom_half(void (* fn)(void *),void * data)210 void unregister_bottom_half(void (*fn)(void *), void *data)
211 {
212 	struct bottom_half *bh;
213 	struct list_head *lbh;
214 	foreach(struct bottom_half, bh, lbh, bottom_halves) if (bh->fn == fn && bh->data == data) {
215 		del_from_list(bh);
216 		mem_free(bh);
217 		return;
218 	}
219 }
220 
check_bottom_halves(void)221 void check_bottom_halves(void)
222 {
223 	struct bottom_half *bh;
224 	void (*fn)(void *);
225 	void *data;
226 	rep:
227 	if (list_empty(bottom_halves)) return;
228 	bh = list_struct(bottom_halves.prev, struct bottom_half);
229 	fn = bh->fn;
230 	data = bh->data;
231 	del_from_list(bh);
232 	mem_free(bh);
233 #ifdef DEBUG_CALLS
234 	fprintf(stderr, "call: bh %p\n", fn);
235 #endif
236 	pr(fn(data)) {
237 #ifdef OOPS
238 		free_list(struct bottom_half, bottom_halves);
239 		return;
240 #endif
241 	};
242 #ifdef DEBUG_CALLS
243 	fprintf(stderr, "bh done\n");
244 #endif
245 	goto rep;
246 }
247 
248 #define CHK_BH if (!list_empty(bottom_halves)) check_bottom_halves()
249 
250 
restrict_fds(void)251 static void restrict_fds(void)
252 {
253 #if defined(RLIMIT_OFILE) && !defined(RLIMIT_NOFILE)
254 #define RLIMIT_NOFILE RLIMIT_OFILE
255 #endif
256 #if defined(HAVE_GETRLIMIT) && defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
257 	struct rlimit limit;
258 	int rs;
259 	EINTRLOOP(rs, getrlimit(RLIMIT_NOFILE, &limit));
260 	if (rs)
261 		goto skip_limit;
262 	if (limit.rlim_cur > FD_SETSIZE) {
263 		limit.rlim_cur = FD_SETSIZE;
264 		EINTRLOOP(rs, setrlimit(RLIMIT_NOFILE, &limit));
265 	}
266 skip_limit:;
267 #endif
268 }
269 
270 unsigned char *sh_file;
271 int sh_line;
272 
273 #ifdef USE_LIBEVENT
274 
275 static int event_enabled = 0;
276 
277 #ifndef HAVE_EVENT_GET_STRUCT_EVENT_SIZE
278 #define sizeof_struct_event		sizeof(struct event)
279 #else
280 #define sizeof_struct_event		(event_get_struct_event_size())
281 #endif
282 
timer_event(struct timer * tm)283 static inline struct event *timer_event(struct timer *tm)
284 {
285 	return (struct event *)((unsigned char *)tm - sizeof_struct_event);
286 }
287 
288 #ifdef HAVE_EVENT_BASE_SET
289 static struct event_base *event_base;
290 #endif
291 
event_callback(int h,short ev,void * data)292 static void event_callback(int h, short ev, void *data)
293 {
294 #ifndef EV_PERSIST
295 	if (event_add((struct event *)data, NULL) == -1)
296 		fatal_exit("ERROR: event_add failed: %s", strerror(errno));
297 #endif
298 	if (!(ev & EV_READ) == !(ev & EV_WRITE))
299 		internal_error("event_callback: invalid flags %d on handle %d", (int)ev, h);
300 	if (ev & EV_READ) {
301 #if defined(HAVE_LIBEV)
302 		/* Old versions of libev badly interact with fork and fire
303 		 * events spuriously. */
304 		if (ev_version_major() < 4 && !can_read(h)) return;
305 #endif
306 		pr(threads[h].read_func(threads[h].data)) { }
307 	} else {
308 #if defined(HAVE_LIBEV)
309 		/* Old versions of libev badly interact with fork and fire
310 		 * events spuriously. */
311 		if (ev_version_major() < 4 && !can_write(h)) return;
312 #endif
313 		pr(threads[h].write_func(threads[h].data)) { }
314 	}
315 	CHK_BH;
316 }
317 
timer_callback(int h,short ev,void * data)318 static void timer_callback(int h, short ev, void *data)
319 {
320 	struct timer *tm = data;
321 	pr(tm->func(tm->data)) { }
322 	kill_timer(tm);
323 	CHK_BH;
324 }
325 
set_event_for_action(int h,void (* func)(void *),struct event ** evptr,short evtype)326 static void set_event_for_action(int h, void (*func)(void *), struct event **evptr, short evtype)
327 {
328 	if (func) {
329 		if (!*evptr) {
330 #ifdef EV_PERSIST
331 			evtype |= EV_PERSIST;
332 #endif
333 			*evptr = mem_alloc(sizeof_struct_event);
334 			event_set(*evptr, h, evtype, event_callback, *evptr);
335 #ifdef HAVE_EVENT_BASE_SET
336 			if (event_base_set(event_base, *evptr) == -1)
337 				fatal_exit("ERROR: event_base_set failed: %s at %s:%d, handle %d", strerror(errno), sh_file, sh_line, h);
338 #endif
339 		}
340 		if (event_add(*evptr, NULL) == -1)
341 			fatal_exit("ERROR: event_add failed: %s at %s:%d, handle %d", strerror(errno), sh_file, sh_line, h);
342 	} else {
343 		if (*evptr) {
344 			if (event_del(*evptr) == -1)
345 				fatal_exit("ERROR: event_del failed: %s at %s:%d, handle %d", strerror(errno), sh_file, sh_line, h);
346 		}
347 	}
348 }
349 
set_events_for_handle(int h)350 static void set_events_for_handle(int h)
351 {
352 	set_event_for_action(h, threads[h].read_func, &threads[h].read_event, EV_READ);
353 	set_event_for_action(h, threads[h].write_func, &threads[h].write_event, EV_WRITE);
354 }
355 
set_event_for_timer(struct timer * tm)356 static void set_event_for_timer(struct timer *tm)
357 {
358 	struct timeval tv;
359 	struct event *ev = timer_event(tm);
360 	timeout_set(ev, timer_callback, tm);
361 #ifdef HAVE_EVENT_BASE_SET
362 	if (event_base_set(event_base, ev) == -1)
363 		fatal_exit("ERROR: event_base_set failed: %s", strerror(errno));
364 #endif
365 	tv.tv_sec = tm->interval / 1000;
366 	tv.tv_usec = (tm->interval % 1000) * 1000;
367 #if defined(HAVE_LIBEV)
368 	if (!tm->interval && ev_version_major() < 4) {
369 		/* libev bug */
370 		tv.tv_usec = 1;
371 	}
372 #endif
373 	if (timeout_add(ev, &tv) == -1)
374 		fatal_exit("ERROR: timeout_add failed: %s", strerror(errno));
375 }
376 
enable_libevent(void)377 static void enable_libevent(void)
378 {
379 	int i;
380 	struct timer *tm;
381 	struct list_head *ltm;
382 
383 	if (disable_libevent)
384 		return;
385 
386 #if !defined(NO_FORK_ON_EXIT) && defined(HAVE_KQUEUE) && !defined(HAVE_EVENT_REINIT)
387 	/* kqueue doesn't work after fork */
388 	if (!F)
389 		return;
390 #endif
391 
392 #if defined(HAVE_EVENT_CONFIG_SET_FLAG)
393 	{
394 		struct event_config *cfg;
395 		cfg = event_config_new();
396 		if (!cfg)
397 			return;
398 		if (event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK) == -1) {
399 			event_config_free(cfg);
400 			return;
401 		}
402 		event_base = event_base_new_with_config(cfg);
403 		event_config_free(cfg);
404 		if (!event_base)
405 			return;
406 	}
407 #elif defined(HAVE_EVENT_BASE_NEW)
408 	event_base = event_base_new();
409 	if (!event_base)
410 		return;
411 #elif defined(HAVE_EVENT_BASE_SET)
412 	event_base = event_init();
413 	if (!event_base)
414 		return;
415 #else
416 	event_init();
417 #endif
418 	event_enabled = 1;
419 
420 	sh_file = (unsigned char *)__FILE__;
421 	sh_line = __LINE__;
422 	for (i = 0; i < w_max; i++)
423 		set_events_for_handle(i);
424 
425 	foreach(struct timer, tm, ltm, timers)
426 		set_event_for_timer(tm);
427 }
428 
terminate_libevent(void)429 static void terminate_libevent(void)
430 {
431 	int i;
432 	if (event_enabled) {
433 		for (i = 0; i < n_threads; i++) {
434 			set_event_for_action(i, NULL, &threads[i].read_event, EV_READ);
435 			if (threads[i].read_event)
436 				mem_free(threads[i].read_event);
437 			set_event_for_action(i, NULL, &threads[i].write_event, EV_WRITE);
438 			if (threads[i].write_event)
439 				mem_free(threads[i].write_event);
440 		}
441 #ifdef HAVE_EVENT_BASE_FREE
442 		event_base_free(event_base);
443 #endif
444 		event_enabled = 0;
445 	}
446 }
447 
do_event_loop(int flags)448 static void do_event_loop(int flags)
449 {
450 	int e;
451 #ifdef HAVE_EVENT_BASE_SET
452 	e = event_base_loop(event_base, flags);
453 #else
454 	e = event_loop(flags);
455 #endif
456 	if (e == -1)
457 		fatal_exit("ERROR: event_base_loop failed: %s", strerror(errno));
458 }
459 
460 #endif
461 
add_event_string(unsigned char ** s,int * l,struct terminal * term)462 void add_event_string(unsigned char **s, int *l, struct terminal *term)
463 {
464 #ifdef USE_LIBEVENT
465 	if (!event_enabled)
466 #endif
467 		add_to_str(s, l, get_text_translation(TEXT_(T_SELECT_SYSCALL), term));
468 #ifdef USE_LIBEVENT
469 	if (!event_enabled)
470 		add_to_str(s, l, cast_uchar " (");
471 #ifdef HAVE_LIBEVENT
472 	add_to_str(s, l, cast_uchar "LibEvent");
473 #elif defined(HAVE_LIBEV)
474 	add_to_str(s, l, cast_uchar "LibEv");
475 #else
476 	add_to_str(s, l, cast_uchar "LibEvent");
477 #endif
478 #ifdef HAVE_EVENT_GET_VERSION
479 	add_chr_to_str(s, l, ' ');
480 	{
481 #if defined(HAVE_LIBEV)
482 				/* old libev report bogus version */
483 		if (!casestrcmp(cast_uchar event_get_version(), cast_uchar "EV_VERSION_MAJOR.EV_VERSION_MINOR")) {
484 			add_num_to_str(s, l, ev_version_major());
485 			add_chr_to_str(s, l, '.');
486 			add_num_to_str(s, l, ev_version_minor());
487 		} else
488 #endif
489 		add_to_str(s, l, cast_uchar event_get_version());
490 	}
491 #endif
492 	if (!event_enabled) {
493 		add_chr_to_str(s, l, ' ');
494 		add_to_str(s, l, get_text_translation(TEXT_(T_dISABLED), term));
495 		add_chr_to_str(s, l, ')');
496 	} else {
497 #if defined(HAVE_EVENT_BASE_GET_METHOD)
498 		add_chr_to_str(s, l, ' ');
499 		add_to_str(s, l, cast_uchar event_base_get_method(event_base));
500 #elif defined(HAVE_EVENT_GET_METHOD)
501 		add_chr_to_str(s, l, ' ');
502 		add_to_str(s, l, cast_uchar event_get_method());
503 #endif
504 	}
505 #endif
506 }
507 
508 
509 static uttime last_time;
510 
check_timers(void)511 static void check_timers(void)
512 {
513 	uttime interval = get_time() - last_time;
514 	struct timer *
515 #ifdef OOPS
516 		volatile
517 #endif
518 		t;		/* volatile because of setjmp */
519 	struct list_head *
520 #ifdef OOPS
521 		volatile	/* volatile because of setjmp */
522 #endif
523 		lt;
524 	foreach(struct timer, t, lt, timers) {
525 		if (t->interval < interval)
526 			t->interval = 0;
527 		else
528 			t->interval -= interval;
529 	}
530 	while (!list_empty(timers)) {
531 		struct timer *t = list_struct(timers.next, struct timer);
532 		if (t->interval)
533 			break;
534 #ifdef DEBUG_CALLS
535 		fprintf(stderr, "call: timer %p\n", t->func);
536 #endif
537 		pr(t->func(t->data)) break;
538 #ifdef DEBUG_CALLS
539 		fprintf(stderr, "timer done\n");
540 #endif
541 		kill_timer(t);
542 		CHK_BH;
543 	}
544 	last_time += interval;
545 }
546 
install_timer(uttime t,void (* func)(void *),void * data)547 struct timer *install_timer(uttime t, void (*func)(void *), void *data)
548 {
549 	struct timer *tm;
550 #ifdef USE_LIBEVENT
551 	{
552 		unsigned char *q = mem_alloc(sizeof_struct_event + sizeof(struct timer));
553 		tm = (struct timer *)(q + sizeof_struct_event);
554 	}
555 #else
556 	tm = mem_alloc(sizeof(struct timer));
557 #endif
558 	tm->interval = t;
559 	tm->func = func;
560 	tm->data = data;
561 #ifdef USE_LIBEVENT
562 	if (event_enabled) {
563 		set_event_for_timer(tm);
564 		add_to_list(timers, tm);
565 	} else
566 #endif
567 	{
568 		struct timer *tt;
569 		struct list_head *ltt;
570 		foreach(struct timer, tt, ltt, timers) if (tt->interval >= t) break;
571 		add_before_list_entry(ltt, &tm->list_entry);
572 	}
573 	return tm;
574 }
575 
kill_timer(struct timer * tm)576 void kill_timer(struct timer *tm)
577 {
578 	del_from_list(tm);
579 #ifdef USE_LIBEVENT
580 	if (event_enabled)
581 		timeout_del(timer_event(tm));
582 	mem_free(timer_event(tm));
583 #else
584 	mem_free(tm);
585 #endif
586 }
587 
get_handler(int fd,int tp)588 void (*get_handler(int fd, int tp))(void *)
589 {
590 	if (fd < 0)
591 		internal_error("get_handler: handle %d", fd);
592 	if (fd >= w_max)
593 		return NULL;
594 	switch (tp) {
595 		case H_READ:	return threads[fd].read_func;
596 		case H_WRITE:	return threads[fd].write_func;
597 	}
598 	internal_error("get_handler: bad type %d", tp);
599 	return NULL;
600 }
601 
get_handler_data(int fd)602 void *get_handler_data(int fd)
603 {
604 	if (fd < 0)
605 		internal_error("get_handler: handle %d", fd);
606 	if (fd >= w_max)
607 		return NULL;
608 	return threads[fd].data;
609 }
610 
set_handlers_file_line(int fd,void (* read_func)(void *),void (* write_func)(void *),void * data)611 void set_handlers_file_line(int fd, void (*read_func)(void *), void (*write_func)(void *), void *data)
612 {
613 	if (fd < 0)
614 		goto invl;
615 #if defined(DEBUG) && !defined(socket)
616 	{
617 		struct stat st;
618 		int rs;
619 		EINTRLOOP(rs, fstat(fd, &st));
620 		if (rs == -1 && errno == EBADF) {
621 			goto invl;
622 		}
623 	}
624 #endif
625 #if defined(USE_POLL) && defined(USE_LIBEVENT)
626 	if (!event_enabled)
627 #endif
628 		if (fd >= (int)FD_SETSIZE) {
629 			fatal_exit("too big handle %d at %s:%d", fd, sh_file, sh_line);
630 			return;
631 		}
632 	if (fd >= n_threads) {
633 		if ((unsigned)fd > (unsigned)MAXINT / sizeof(struct thread) - 1) overalloc();
634 		threads = mem_realloc(threads, (fd + 1) * sizeof(struct thread));
635 		memset(threads + n_threads, 0, (fd + 1 - n_threads) * sizeof(struct thread));
636 		n_threads = fd + 1;
637 	}
638 	if (threads[fd].read_func == read_func && threads[fd].write_func == write_func && threads[fd].data == data)
639 		return;
640 	threads[fd].read_func = read_func;
641 	threads[fd].write_func = write_func;
642 	threads[fd].data = data;
643 	if (read_func || write_func) {
644 		if (fd >= w_max) w_max = fd + 1;
645 	} else if (fd == w_max - 1) {
646 		int i;
647 		for (i = fd - 1; i >= 0; i--)
648 			if (threads[i].read_func || threads[i].write_func)
649 				break;
650 		w_max = i + 1;
651 	}
652 #ifdef USE_LIBEVENT
653 	if (event_enabled) {
654 		set_events_for_handle(fd);
655 		return;
656 	}
657 #endif
658 	if (read_func) FD_SET(fd, &w_read);
659 	else {
660 		FD_CLR(fd, &w_read);
661 		FD_CLR(fd, &x_read);
662 	}
663 	if (write_func) FD_SET(fd, &w_write);
664 	else {
665 		FD_CLR(fd, &w_write);
666 		FD_CLR(fd, &x_write);
667 	}
668 	return;
669 
670 invl:
671 	internal_error("invalid set_handlers call at %s:%d: %d, %p, %p, %p", sh_file, sh_line, fd, read_func, write_func, data);
672 }
673 
clear_events(int h,int blocking)674 void clear_events(int h, int blocking)
675 {
676 #if !defined(O_NONBLOCK) && !defined(FIONBIO)
677 	blocking = 1;
678 #endif
679 	while (blocking ? can_read(h) : 1) {
680 		unsigned char c[64];
681 		int rd;
682 		EINTRLOOP(rd, (int)read(h, c, sizeof c));
683 		if (rd != sizeof c) break;
684 	}
685 }
686 
687 #if defined(NSIG) && NSIG > 32
688 #define NUM_SIGNALS	NSIG
689 #else
690 #define NUM_SIGNALS	32
691 #endif
692 
693 #ifndef NO_SIGNAL_HANDLERS
694 
clear_events_ptr(void * handle)695 static void clear_events_ptr(void *handle)
696 {
697 	clear_events((int)(my_intptr_t)handle, 0);
698 }
699 
700 
701 struct signal_handler {
702 	void (*fn)(void *);
703 	void *data;
704 	int critical;
705 };
706 
707 static volatile int signal_mask[NUM_SIGNALS];
708 static volatile struct signal_handler signal_handlers[NUM_SIGNALS];
709 
710 static pid_t signal_pid;
711 int signal_pipe[2] = { -1, -1 };
712 
got_signal(int sig)713 SIGNAL_HANDLER static void got_signal(int sig)
714 {
715 	void (*fn)(void *);
716 	int sv_errno = errno;
717 		/*fprintf(stderr, "ERROR: signal number: %d\n", sig);*/
718 
719 #if !defined(HAVE_SIGACTION)
720 	do_signal(sig, got_signal);
721 #endif
722 
723 	/* if we get signal from a forked child, don't do anything */
724 	if (getpid() != signal_pid) goto ret;
725 
726 	if (sig >= NUM_SIGNALS || sig < 0) {
727 		/*error("ERROR: bad signal number: %d", sig);*/
728 		goto ret;
729 	}
730 	fn = signal_handlers[sig].fn;
731 	if (!fn) goto ret;
732 	if (signal_handlers[sig].critical) {
733 		fn(signal_handlers[sig].data);
734 		goto ret;
735 	}
736 	signal_mask[sig] = 1;
737 	if (can_write(signal_pipe[1])) {
738 		int wr;
739 		EINTRLOOP(wr, (int)write(signal_pipe[1], "", 1));
740 	}
741 	ret:
742 	errno = sv_errno;
743 }
744 
745 #ifdef HAVE_SIGACTION
746 static struct sigaction sa_zero;
747 #endif
748 
749 #endif
750 
install_signal_handler(int sig,void (* fn)(void *),void * data,int critical)751 void install_signal_handler(int sig, void (*fn)(void *), void *data, int critical)
752 {
753 #if defined(NO_SIGNAL_HANDLERS)
754 #elif defined(HAVE_SIGACTION)
755 	int rs;
756 	struct sigaction sa = sa_zero;
757 	/*debug("install (%d) -> %p,%d", sig, fn, critical);*/
758 	if (sig >= NUM_SIGNALS || sig < 0) {
759 		internal_error("bad signal number: %d", sig);
760 		return;
761 	}
762 	if (!fn) sa.sa_handler = SIG_IGN;
763 	else sa.sa_handler = (void (*)(int))got_signal;
764 	sig_fill_set(&sa.sa_mask);
765 	sa.sa_flags = SA_RESTART;
766 	if (!fn)
767 		EINTRLOOP(rs, sigaction(sig, &sa, NULL));
768 	signal_handlers[sig].fn = fn;
769 	signal_handlers[sig].data = data;
770 	signal_handlers[sig].critical = critical;
771 	if (fn)
772 		EINTRLOOP(rs, sigaction(sig, &sa, NULL));
773 #else
774 	if (!fn) do_signal(sig, SIG_IGN);
775 	signal_handlers[sig].fn = fn;
776 	signal_handlers[sig].data = data;
777 	signal_handlers[sig].critical = critical;
778 	if (fn) do_signal(sig, got_signal);
779 #endif
780 }
781 
interruptible_signal(int sig,int in)782 void interruptible_signal(int sig, int in)
783 {
784 #if defined(HAVE_SIGACTION) && !defined(NO_SIGNAL_HANDLERS)
785 	struct sigaction sa = sa_zero;
786 	int rs;
787 	if (sig >= NUM_SIGNALS || sig < 0) {
788 		internal_error("bad signal number: %d", sig);
789 		return;
790 	}
791 	if (!signal_handlers[sig].fn) return;
792 	sa.sa_handler = (void (*)(int))got_signal;
793 	sig_fill_set(&sa.sa_mask);
794 	if (!in) sa.sa_flags = SA_RESTART;
795 	EINTRLOOP(rs, sigaction(sig, &sa, NULL));
796 #endif
797 }
798 
799 static sigset_t sig_old_mask;
800 static int sig_unblock = 0;
801 
block_signals(int except1,int except2)802 void block_signals(int except1, int except2)
803 {
804 	int rs;
805 	sigset_t mask;
806 	sig_fill_set(&mask);
807 #ifdef HAVE_SIGDELSET
808 	if (except1) sigdelset(&mask, except1);
809 	if (except2) sigdelset(&mask, except2);
810 #ifdef SIGILL
811 	sigdelset(&mask, SIGILL);
812 #endif
813 #ifdef SIGABRT
814 	sigdelset(&mask, SIGABRT);
815 #endif
816 #ifdef SIGFPE
817 	sigdelset(&mask, SIGFPE);
818 #endif
819 #ifdef SIGSEGV
820 	sigdelset(&mask, SIGSEGV);
821 #endif
822 #ifdef SIGBUS
823 	sigdelset(&mask, SIGBUS);
824 #endif
825 #else
826 	if (except1 || except2) return;
827 #endif
828 	EINTRLOOP(rs, do_sigprocmask(SIG_BLOCK, &mask, &sig_old_mask));
829 	if (!rs) sig_unblock = 1;
830 }
831 
unblock_signals(void)832 void unblock_signals(void)
833 {
834 	int rs;
835 	if (sig_unblock) {
836 		EINTRLOOP(rs, do_sigprocmask(SIG_SETMASK, &sig_old_mask, NULL));
837 		sig_unblock = 0;
838 	}
839 }
840 
check_signals(void)841 static int check_signals(void)
842 {
843 	int r = 0;
844 #ifndef NO_SIGNAL_HANDLERS
845 	volatile int i;	/* volatile because of setjmp */
846 	for (i = 0; i < NUM_SIGNALS; i++)
847 		if (signal_mask[i]) {
848 			signal_mask[i] = 0;
849 			if (signal_handlers[i].fn) {
850 #ifdef DEBUG_CALLS
851 				fprintf(stderr, "call: signal %d -> %p\n", i, signal_handlers[i].fn);
852 #endif
853 				pr(signal_handlers[i].fn(signal_handlers[i].data)) {
854 #ifdef OOPS
855 					return 1;
856 #endif
857 }
858 #ifdef DEBUG_CALLS
859 				fprintf(stderr, "signal done\n");
860 #endif
861 			}
862 			CHK_BH;
863 			r = 1;
864 		}
865 #endif
866 	return r;
867 }
868 
869 #ifdef SIGCHLD
sigchld(void * p)870 static void sigchld(void *p)
871 {
872 	pid_t pid;
873 #ifndef WNOHANG
874 	EINTRLOOP(pid, wait(NULL));
875 #else
876 	do {
877 		EINTRLOOP(pid, waitpid(-1, NULL, WNOHANG));
878 	} while (pid > 0);
879 #endif
880 }
881 
set_sigcld(void)882 void set_sigcld(void)
883 {
884 	install_signal_handler(SIGCHLD, sigchld, NULL, 1);
885 }
886 #else
set_sigcld(void)887 void set_sigcld(void)
888 {
889 }
890 #endif
891 
892 #ifdef HAVE_OPENMP
893 
894 static int num_threads = -1;
895 
omp_start(void)896 int omp_start(void)
897 {
898 	int thr;
899 	if (disable_openmp || num_threads == 1)
900 		return 1;
901 	block_signals(0, 0);
902 	if (num_threads != -1)
903 		return num_threads;
904 	omp_set_dynamic(0);
905 	thr = omp_get_max_threads();
906 	if (thr > OPENMP_MAX_THREADS)
907 		thr = OPENMP_MAX_THREADS;
908 	omp_set_num_threads(thr);
909 	if (thr > 1) {
910 #pragma omp parallel shared(thr)
911 #pragma omp single
912 			thr = omp_get_num_threads();
913 		omp_set_num_threads(thr);
914 	}
915 	num_threads = thr;
916 	if (thr == 1)
917 		unblock_signals();
918 	return thr;
919 }
920 
omp_end(void)921 void omp_end(void)
922 {
923 	if (disable_openmp || num_threads == 1)
924 		return;
925 	unblock_signals();
926 }
927 
928 #endif
929 
reinit_child(void)930 void reinit_child(void)
931 {
932 #if !defined(NO_SIGNAL_HANDLERS)
933 	signal_pid = getpid();
934 #endif
935 #ifdef USE_LIBEVENT
936 	if (event_enabled) {
937 #ifdef HAVE_EVENT_REINIT
938 		if (event_reinit(event_base))
939 			fatal_exit("ERROR: event_reinit failed: %s", strerror(errno));
940 #endif
941 	}
942 #endif
943 }
944 
945 int terminate_loop = 0;
946 
select_loop(void (* init)(void))947 void select_loop(void (*init)(void))
948 {
949 #if !defined(USE_LIBEVENT) || !defined(USE_POLL)
950 	restrict_fds();
951 #endif
952 
953 #if !defined(NO_SIGNAL_HANDLERS)
954 #if defined(HAVE_SIGACTION)
955 	memset(&sa_zero, 0, sizeof sa_zero);
956 #endif
957 	memset((void *)signal_mask, 0, sizeof signal_mask);
958 	memset((void *)signal_handlers, 0, sizeof signal_handlers);
959 #endif
960 	FD_ZERO(&w_read);
961 	FD_ZERO(&w_write);
962 	w_max = 0;
963 	last_time = get_time();
964 	ignore_signals();
965 #if !defined(NO_SIGNAL_HANDLERS)
966 	signal_pid = getpid();
967 	if (c_pipe(signal_pipe)) {
968 		fatal_exit("ERROR: can't create pipe for signal handling");
969 	}
970 	set_nonblock(signal_pipe[0]);
971 	set_nonblock(signal_pipe[1]);
972 	set_handlers(signal_pipe[0], clear_events_ptr, NULL, (void *)(my_intptr_t)signal_pipe[0]);
973 #endif
974 	init();
975 	CHK_BH;
976 
977 #ifdef USE_LIBEVENT
978 #ifdef G
979 	if (!F || !(drv->flags & GD_NO_LIBEVENT))
980 #endif
981 	{
982 		enable_libevent();
983 	}
984 #if defined(USE_POLL)
985 	if (!event_enabled) {
986 		restrict_fds();
987 	}
988 #endif
989 	if (event_enabled) {
990 		while (!terminate_loop) {
991 			check_signals();
992 			if (!F) {
993 				do_event_loop(EVLOOP_NONBLOCK);
994 				check_signals();
995 				redraw_all_terminals();
996 			}
997 			if (terminate_loop) break;
998 			test_detach_console();
999 			do_event_loop(EVLOOP_ONCE);
1000 		}
1001 		nopr();
1002 	} else
1003 #endif
1004 
1005 	while (!terminate_loop) {
1006 		volatile int n, i;	/* volatile because of setjmp */
1007 		int ww_max;
1008 		struct timeval tv;
1009 		struct timeval *tm = NULL;
1010 		check_signals();
1011 		check_timers();
1012 		if (!F) redraw_all_terminals();
1013 		test_detach_console();
1014 #ifdef OS_BAD_SIGNALS
1015 	/* Cygwin has buggy signals that sometimes don't interrupt select.
1016 	   So don't wait indefinitely in it. */
1017 		tv.tv_sec = 1;
1018 		tv.tv_usec = 0;
1019 		tm = &tv;
1020 #endif
1021 		if (!list_empty(timers)) {
1022 			uttime tt = list_struct(timers.next, struct timer)->interval + 1;
1023 #ifdef OS_BAD_SIGNALS
1024 			if (tt < 1000)
1025 #endif
1026 			{
1027 				tv.tv_sec = tt / 1000 < MAXINT ? (int)(tt / 1000) : MAXINT;
1028 				tv.tv_usec = (tt % 1000) * 1000;
1029 				tm = &tv;
1030 			}
1031 		}
1032 		memcpy(&x_read, &w_read, sizeof(fd_set));
1033 		memcpy(&x_write, &w_write, sizeof(fd_set));
1034 		if (terminate_loop) break;
1035 		/*if (!w_max && list_empty(timers)) {
1036 			break;
1037 		}*/
1038 			/*{
1039 				int i;
1040 				printf("\nR:");
1041 				for (i = 0; i < 256; i++) if (FD_ISSET(i, &x_read)) printf("%d,", i);
1042 				printf("\nW:");
1043 				for (i = 0; i < 256; i++) if (FD_ISSET(i, &x_write)) printf("%d,", i);
1044 				fflush(stdout);
1045 			}*/
1046 #ifdef DEBUG_CALLS
1047 		fprintf(stderr, "select\n");
1048 #endif
1049 		ww_max = w_max;
1050 		if ((n = loop_select(w_max, &x_read, &x_write, NULL, tm)) < 0) {
1051 #ifdef DEBUG_CALLS
1052 			fprintf(stderr, "select intr\n");
1053 #endif
1054 			if (errno != EINTR) {
1055 				fatal_exit("ERROR: select failed: %s", strerror(errno));
1056 			}
1057 			continue;
1058 		}
1059 #ifdef DEBUG_CALLS
1060 		fprintf(stderr, "select done\n");
1061 #endif
1062 		check_signals();
1063 		check_timers();
1064 		/*
1065 		 * EMX has broken select. It should return the total number of
1066 		 * bits set, but instead it returns the number of handles for
1067 		 * which some activity is reported.
1068 		 * Sometimes it returns unusually high values.
1069 		 */
1070 		i = -1;
1071 		while (n > 0 && ++i < ww_max) {
1072 			int k = 0;
1073 			if (FD_ISSET(i, &x_read)) {
1074 				if (threads[i].read_func) {
1075 #ifdef DEBUG_CALLS
1076 					fprintf(stderr, "call: read %d -> %p\n", i, threads[i].read_func);
1077 #endif
1078 					pr(threads[i].read_func(threads[i].data)) continue;
1079 #ifdef DEBUG_CALLS
1080 					fprintf(stderr, "read done\n");
1081 #endif
1082 					CHK_BH;
1083 				}
1084 				k = 1;
1085 			}
1086 			if (FD_ISSET(i, &x_write)) {
1087 				if (threads[i].write_func) {
1088 #ifdef DEBUG_CALLS
1089 					fprintf(stderr, "call: write %d -> %p\n", i, threads[i].write_func);
1090 #endif
1091 					pr(threads[i].write_func(threads[i].data)) continue;
1092 #ifdef DEBUG_CALLS
1093 					fprintf(stderr, "write done\n");
1094 #endif
1095 					CHK_BH;
1096 				}
1097 				k = 1;
1098 			}
1099 			n -= k;
1100 		}
1101 		nopr();
1102 	}
1103 #ifdef DEBUG_CALLS
1104 	fprintf(stderr, "exit loop\n");
1105 #endif
1106 	nopr();
1107 }
1108 
terminate_select(void)1109 void terminate_select(void)
1110 {
1111 #ifdef USE_LIBEVENT
1112 	terminate_libevent();
1113 #endif
1114 	mem_free(threads);
1115 }
1116