forked from cfadmin-cn/cfadmin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore.c
More file actions
303 lines (258 loc) · 7.25 KB
/
core.c
File metadata and controls
303 lines (258 loc) · 7.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#include "core.h"
#define MASTER (1)
#define WORKER (2)
#define IS_MASTER(mode) (mode == MASTER)
#define IS_WORKER(mode) (mode == WORKER)
#define LUALIBS_PATH \
"lualib/?.lua;;lualib/?/init.lua;;" \
"lualib/?.lc;;lualib/?/init.lc;;" \
\
"3rd/?.lua;;3rd/?/init.lua;;" \
"3rd/?.lc;;3rd/?/init.lc;;" \
\
"script/?.lua;;script/?/init.lua;;" \
"script/?.lc;;script/?/init.lc;;"
#define LUACLIBS_PATH \
"luaclib/?.so;;luaclib/lib?.so;;" \
"3rd/?.so;;3rd/lib?.so;;" \
\
"3rd/?.dylib;;3rd/lib?.dylib;;" \
"luaclib/?.dylib;;luaclib/lib?.dylib;;" \
\
"luaclib/?.dll;;luaclib/msys-?.dll;;" \
"3rd/?.dll;;3rd/msys-?.dll;;"
/* Master 进程 `Main`函数 */
static const char* master_boot = "\n\
local process = require 'process.master'\n\
\
process.init(...)\n\
\
local f = loadfile('script/boot.lua')\n\
\
if f then\n\
\
require 'cf'.fork(f)\n\
\
end\n\
require 'cf'.wait()\n\
";
/* Worker 进程 `Main`函数 */
static const char* worker_boot = "\n\
local process = require 'process.worker'\n\
\
process.init()\n\
\
local f = assert(loadfile(...))\n\
\
require 'cf'.fork(f)\n\
\
require 'cf'.wait()\n\
";
/* 忽略信号 */
static void SIG_IGNORE(core_loop *loop, core_signal *signal, int revents){
return ;
}
/* 退出信号 */
static void SIG_EXIT(core_loop *loop, core_signal *signal, int revents){
/* 只有主进程退出的时候才需要通知子进程退出 */
if (ev_userdata(loop))
kill(0, SIGQUIT);
return exit(EXIT_SUCCESS);
}
/* 内部异常 */
static void EV_ERROR_CB(const char *msg){
LOG("ERROR", msg);
LOG("ERROR", strerror(errno));
if (CORE_LOOP) {
pid_t *pids = (pid_t *)ev_userdata(CORE_LOOP);
if (pids)
kill(0, SIGKILL);
}
/* 减少无效打印, 专注错误提示 */
return exit(EXIT_SUCCESS);
}
/* 为libev内存hook注入日志 */
static void *EV_ALLOC(void *ptr, long nsize){
if (nsize == 0) return xfree(ptr), NULL;
for (;;) {
void *newptr = xrealloc(ptr, nsize);
if (newptr) return newptr;
LOG("WARN", "Allocate failed, Sleep sometime..");
sleep(1);
}
}
/* 为lua内存hook注入日志 */
static void* L_ALLOC(void *ud, void *ptr, size_t osize, size_t nsize){
/* 用户自定义数据 */
(void)ud; (void)osize;
if (nsize == 0) return xfree(ptr), NULL;
for (;;) {
void *newptr = xrealloc(ptr, nsize);
if (newptr) return newptr;
LOG("WARN", "Allocate failed, Sleep sometime..");
sleep(1);
}
}
void init_lua_mode(lua_State *L, int mode) {
/* worker */
if (IS_WORKER(mode) && getenv("cfadmin_isWorker")) {
lua_pushliteral(L, "worker");
lua_createtable(L, 0, 0);
lua_pushliteral(L, "id");
lua_pushinteger(L, getpid() - getppid());
lua_rawset(L, -3);
lua_pushliteral(L, "pid");
lua_pushinteger(L, getpid());
lua_rawset(L, -3);
lua_pushliteral(L, "ppid");
lua_pushinteger(L, getppid());
lua_rawset(L, -3);
lua_pushliteral(L, "nprocess");
lua_pushinteger(L, atoi(getenv("cfadmin_nprocess")));
lua_rawset(L, -3);
lua_rawset(L, -3);
/* Master */
} else if (IS_MASTER(mode)) {
lua_pushliteral(L, "master");
lua_createtable(L, 0, 0);
lua_pushliteral(L, "pid");
lua_pushinteger(L, getpid());
lua_rawset(L, -3);
lua_pushliteral(L, "nprocess");
lua_pushinteger(L, atoi(getenv("cfadmin_nprocess")));
lua_rawset(L, -3);
lua_rawset(L, -3);
}
}
void init_lua_libs(lua_State *L, int mode){
/* lua 标准库 */
luaL_openlibs(L);
lua_pushglobaltable(L);
lua_pushliteral(L, "null");
lua_pushlightuserdata(L, NULL);
lua_rawset(L, -3);
lua_pushliteral(L, "NULL");
lua_pushlightuserdata(L, NULL);
lua_rawset(L, -3);
/*注入*/
init_lua_mode(L, mode);
lua_settop(L, 0);
/* 注入lua搜索域 */
lua_getglobal(L, "package");
/* 注入lualib搜索路径 */
lua_pushliteral(L, LUALIBS_PATH);
lua_setfield(L, 1, "path");
/* 注入luaclib搜索路径 */
lua_pushliteral(L, LUACLIBS_PATH);
lua_setfield(L, 1, "cpath");
lua_settop(L, 0);
/* 优化Lua的GC */
CO_GCRESET(L);
}
/* 注册需要忽略的信号 */
core_signal sighup;
core_signal sigpipe;
core_signal sigtstp;
/* 注册需要退出的信号(docker需要) */
core_signal sigint;
core_signal sigterm;
core_signal sigquit;
static inline void signal_init(){
/* 忽略连接中断信号 */
core_signal_init(&sighup, SIG_IGNORE, SIGHUP);
core_signal_start(CORE_LOOP_ &sighup);
/* 忽略无效的管道读/写信号 */
core_signal_init(&sigpipe, SIG_IGNORE, SIGPIPE);
core_signal_start(CORE_LOOP_ &sigpipe);
/* 忽略Ctrl-Z操作信号 */
core_signal_init(&sigtstp, SIG_IGNORE, SIGTSTP);
core_signal_start(CORE_LOOP_ &sigtstp);
if (ev_userdata(CORE_LOOP)) {
/* TERM信号 显示退出 */
core_signal_init(&sigterm, SIG_EXIT, SIGTERM);
core_signal_start(CORE_LOOP_ &sigterm);
/* INT信号 显示退出 */
core_signal_init(&sigint, SIG_EXIT, SIGINT);
core_signal_start(CORE_LOOP_ &sigint);
/* QUIT信号 显示退出 */
core_signal_init(&sigquit, SIG_EXIT, SIGQUIT);
core_signal_start(CORE_LOOP_ &sigquit);
}
}
int core_worker_run(const char entry[]) {
/* hook libev 内存分配 */
core_ev_set_allocator(EV_ALLOC);
/* hook 事件循环错误信息 */
core_ev_set_syserr_cb(EV_ERROR_CB);
/* 初始化事件循环对象 */
core_loop *loop = core_loop_fork(CORE_LOOP);
int status = 0;
lua_State *L = lua_newstate(L_ALLOC, NULL);
if (!L)
core_exit();
init_lua_libs(L, WORKER);
/* 根据进程运行模式选择不同的启动方式 */
status = getenv("cfadmin_isWorker") ?
luaL_loadbufferx(L, worker_boot, strlen(worker_boot), "=[worker.lua]", "t") : luaL_loadfile(L, entry);
if (status > 1){
LOG("ERROR", lua_tostring(L, -1));
lua_close(L);
core_exit();
}
if (getenv("cfadmin_isWorker")) {
lua_pushstring(L, entry);
}
status = CO_RESUME(L, NULL, lua_gettop(L) - 1);
if (status > 1){
LOG("ERROR", lua_tostring(L, -1));
lua_close(L);
core_exit();
}
if (status == LUA_YIELD)
signal_init();
return core_start(loop, 0);
}
int core_master_run(pid_t *pids, int* pidcount) {
/* hook libev 内存分配 */
core_ev_set_allocator(EV_ALLOC);
/* hook 事件循环错误信息 */
core_ev_set_syserr_cb(EV_ERROR_CB);
/* 初始化事件循环对象 */
core_loop *loop = core_loop_fork(CORE_LOOP);
/* 设置pid */
ev_set_userdata(loop, pids);
/* 初始化信号 */
signal_init();
lua_State *L = lua_newstate(L_ALLOC, NULL);
if (!L){
LOG("ERROR", "New Lua State failed.");
kill(0, SIGQUIT);
core_exit();
}
/* 加载 Lua 标准库 */
init_lua_libs(L, MASTER);
/* 读取文件或默认运行 */
int status = luaL_loadbufferx(L, master_boot, strlen(master_boot), "=[master.lua]", "t");
if (status != LUA_OK) {
lua_close(L);
kill(0, SIGQUIT);
core_exit();
}
/* 注入子进程Pid */
lua_createtable(L, 0, 0);
int index;
for (index = 0; index < *pidcount; index++) {
lua_pushinteger(L, pids[index]);
lua_seti(L, -2, index + 1);
}
/* 开始执行 */
status = CO_RESUME(L, NULL, lua_gettop(L) - 1);
if (status != LUA_YIELD){
LOG("ERROR", lua_tostring(L, -1));
lua_close(L);
kill(0, SIGQUIT);
core_exit();
}
/* 初始化主进程 */
return core_start(loop, 0);
}