1 #include "uwsgi.h"
2 
3 extern struct uwsgi_server uwsgi;
4 
5 /*
6 
7 	the --master-fifo option create a unix named pipe (fifo) you can use to send management
8 	commands to the master:
9 
10 	echo r > myfifo
11 
12 */
13 
14 // this var can be accessed by plugins and hooks
15 void (*uwsgi_fifo_table[256])(int);
16 
uwsgi_fifo_by_slot()17 static char *uwsgi_fifo_by_slot() {
18 	int count = 0;
19 	struct uwsgi_string_list *usl;
20 	uwsgi_foreach(usl, uwsgi.master_fifo) {
21 		if (count == uwsgi.master_fifo_slot) return usl->value;
22 		count++;
23 	}
24 	return uwsgi.master_fifo->value;
25 }
26 
27 #define announce_fifo uwsgi_log_verbose("active master fifo is now %s\n", uwsgi_fifo_by_slot())
28 
uwsgi_fifo_set_slot_zero()29 static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; announce_fifo; }
uwsgi_fifo_set_slot_one()30 static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; announce_fifo; }
uwsgi_fifo_set_slot_two()31 static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; announce_fifo; }
uwsgi_fifo_set_slot_three()32 static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; announce_fifo; }
uwsgi_fifo_set_slot_four()33 static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; announce_fifo; }
uwsgi_fifo_set_slot_five()34 static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; announce_fifo; }
uwsgi_fifo_set_slot_six()35 static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; announce_fifo; }
uwsgi_fifo_set_slot_seven()36 static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; announce_fifo; }
uwsgi_fifo_set_slot_eight()37 static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; announce_fifo; }
uwsgi_fifo_set_slot_nine()38 static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; announce_fifo; }
39 
subscriptions_blocker()40 static void subscriptions_blocker() {
41 	if (uwsgi.subscriptions_blocked) {
42 		uwsgi_log_verbose("subscriptions re-enabled\n");
43 		uwsgi.subscriptions_blocked = 0;
44 	}
45 	else {
46 		uwsgi.subscriptions_blocked = 1;
47 		uwsgi_log_verbose("subscriptions blocked\n");
48 	}
49 }
50 
emperor_rescan()51 static void emperor_rescan() {
52 	if (uwsgi.emperor_pid > 0) {
53 		if (kill(uwsgi.emperor_pid, SIGWINCH)) {
54 			uwsgi_error("emperor_rescan()/kill()");
55 		}
56 	}
57 }
58 
59 /*
60 
61 this is called as soon as possibile allowing plugins (or hooks) to override it
62 
63 */
uwsgi_master_fifo_prepare()64 void uwsgi_master_fifo_prepare() {
65 	int i;
66 	for(i=0;i<256;i++) {
67 		uwsgi_fifo_table[i] = NULL;
68 	}
69 
70 	uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
71 	uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
72 	uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
73 	uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
74 	uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
75 	uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
76 	uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
77 	uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
78 	uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
79 	uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
80 
81 	uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
82 	uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
83 	uwsgi_fifo_table['B'] = vassal_sos;
84 	uwsgi_fifo_table['c'] = uwsgi_chain_reload;
85 	uwsgi_fifo_table['C'] = uwsgi_go_cheap;
86 	uwsgi_fifo_table['E'] = emperor_rescan;
87 	uwsgi_fifo_table['f'] = uwsgi_refork_master;
88 	uwsgi_fifo_table['l'] = uwsgi_log_reopen;
89 	uwsgi_fifo_table['L'] = uwsgi_log_rotate;
90 	uwsgi_fifo_table['p'] = suspend_resume_them_all;
91 	uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
92 	uwsgi_fifo_table['q'] = gracefully_kill_them_all;
93 	uwsgi_fifo_table['Q'] = kill_them_all;
94 	uwsgi_fifo_table['r'] = grace_them_all;
95 	uwsgi_fifo_table['R'] = reap_them_all;
96 	uwsgi_fifo_table['s'] = stats;
97 	uwsgi_fifo_table['S'] = subscriptions_blocker;
98 	uwsgi_fifo_table['w'] = uwsgi_reload_workers;
99 	uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
100 
101 }
102 
uwsgi_master_fifo()103 int uwsgi_master_fifo() {
104 
105 	char *path = uwsgi_fifo_by_slot();
106 
107 	if (unlink(path) != 0 && errno != ENOENT) {
108 		uwsgi_error("uwsgi_master_fifo()/unlink()");
109 	}
110 
111 	if (mkfifo(path, S_IRUSR|S_IWUSR)) {
112 		uwsgi_error("uwsgi_master_fifo()/mkfifo()");
113 		exit(1);
114 	}
115 
116 	int fd = open(path, O_RDONLY|O_NONBLOCK);
117 	if (fd < 0) {
118 		uwsgi_error("uwsgi_master_fifo()/open()");
119 		exit(1);
120 	}
121 
122 	uwsgi_socket_nb(fd);
123 
124 	return fd;
125 }
126 
uwsgi_master_fifo_manage(int fd)127 int uwsgi_master_fifo_manage(int fd) {
128 	unsigned char cmd;
129 	ssize_t rlen = read(fd, &cmd, 1);
130 	if (rlen < 0) {
131 		if (uwsgi_is_again()) return 0;
132 		uwsgi_error("uwsgi_master_fifo_manage()/read()");
133 		exit(1);
134 	}
135 	// fifo destroyed, recreate it
136 	else if (rlen == 0) {
137 		event_queue_del_fd(uwsgi.master_queue, uwsgi.master_fifo_fd, event_queue_read());
138 		close(fd);
139 		uwsgi.master_fifo_fd = uwsgi_master_fifo();
140 		event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
141 		return 0;
142 	}
143 
144 	if (uwsgi_fifo_table[(int) cmd]) {
145 		uwsgi_fifo_table[(int) cmd](0);
146 	}
147 
148 	return 0;
149 }
150