Skip to content

Commit 6ad0d72

Browse files
committed
support signal event for (#423)(#458)
1 parent 3564a4f commit 6ad0d72

File tree

8 files changed

+89
-5
lines changed

8 files changed

+89
-5
lines changed

README-CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
## ✨ 特性
5353

5454
- 跨平台(Linux, Windows, macOS, Android, iOS, BSD, Solaris)
55-
- 高性能事件循环(网络IO事件、定时器事件、空闲事件、自定义事件)
55+
- 高性能事件循环(网络IO事件、定时器事件、空闲事件、自定义事件、信号
5656
- TCP/UDP服务端/客户端/代理
5757
- TCP支持心跳、重连、转发、多线程安全write和close等特性
5858
- 内置常见的拆包模式(固定包长、分界符、头部长度字段)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ but simpler api and richer protocols.
2828
## ✨ Features
2929

3030
- Cross-platform (Linux, Windows, macOS, Android, iOS, BSD, Solaris)
31-
- High-performance EventLoop (IO, timer, idle, custom)
31+
- High-performance EventLoop (IO, timer, idle, custom, signal)
3232
- TCP/UDP client/server/proxy
3333
- TCP supports heartbeat, reconnect, upstream, MultiThread-safe write and close, etc.
3434
- Built-in common unpacking modes (FixedLength, Delimiter, LengthField)

docs/API.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@
479479
- htimer_reset
480480
- hidle_add
481481
- hidle_del
482+
- hsignal_add
483+
- hsignal_del
482484

483485
### nlog.h
484486
- network_logger

docs/cn/hloop.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct hevent_s {
4343
// 获取事件用户数据
4444
#define hevent_userdata(ev) (((hevent_t*)(ev))->userdata)
4545

46-
// hidle_t、htimer_t、hio_t皆是继承自hevent_t,继承上面的数据成员和函数方法
46+
// hio_t、htimer_t、hsignal_t、hidle_t皆是继承自hevent_t,继承上面的数据成员和函数方法
4747

4848
// 新建事件循环
4949
hloop_t* hloop_new(int flags DEFAULT(HLOOP_FLAG_AUTO_FREE));
@@ -107,6 +107,12 @@ void* hloop_userdata(hloop_t* loop);
107107
// 投递事件
108108
void hloop_post_event(hloop_t* loop, hevent_t* ev);
109109

110+
// 添加信号处理
111+
hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo);
112+
113+
// 删除信号处理
114+
void hsignal_del(hsignal_t* sig);
115+
110116
// 添加空闲事件
111117
hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
112118

event/hevent.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define HIO_READ_UNTIL_DELIM 0x4
2626

2727
ARRAY_DECL(hio_t*, io_array);
28+
ARRAY_DECL(hsignal_t*, signal_array);
2829
QUEUE_DECL(hevent_t, event_queue);
2930

3031
struct hloop_s {
@@ -45,6 +46,9 @@ struct hloop_s {
4546
uint32_t npendings;
4647
// pendings: with priority as array.index
4748
hevent_t* pendings[HEVENT_PRIORITY_SIZE];
49+
// signals
50+
struct signal_array signals;
51+
uint32_t nsignals;
4852
// idles
4953
struct list_head idles;
5054
uint32_t nidles;

event/hloop.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,14 @@ static void hloop_cleanup(hloop_t* loop) {
394394
}
395395
heap_init(&loop->realtimers, NULL);
396396

397+
// signals
398+
printd("cleanup signals...\n");
399+
for (int i = 0; i < loop->signals.maxsize; ++i) {
400+
hsignal_t* sig = loop->signals.ptr[i];
401+
HV_FREE(sig);
402+
}
403+
signal_array_cleanup(&loop->signals);
404+
397405
// readbuf
398406
if (loop->readbuf.base && loop->readbuf.len) {
399407
HV_FREE(loop->readbuf.base);
@@ -587,6 +595,55 @@ void* hloop_userdata(hloop_t* loop) {
587595
return loop->userdata;
588596
}
589597

598+
static hloop_t* s_signal_loop = NULL;
599+
static void signal_handler(int signo) {
600+
if (!s_signal_loop) return;
601+
if (signo >= s_signal_loop->signals.maxsize) return;
602+
hsignal_t* sig = s_signal_loop->signals.ptr[signo];
603+
if (!sig) return;
604+
hloop_post_event(s_signal_loop, sig);
605+
}
606+
607+
hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo) {
608+
int max_signo = 64;
609+
#ifdef _NSIG
610+
max_signo = _NSIG;
611+
#endif
612+
if (signo <= 0 || signo >= max_signo) {
613+
hloge("signo %d over %d!", signo, max_signo);
614+
return NULL;
615+
}
616+
if (loop->signals.maxsize == 0) {
617+
signal_array_init(&loop->signals, max_signo);
618+
}
619+
hsignal_t* sig = loop->signals.ptr[signo];
620+
if (sig == NULL) {
621+
HV_ALLOC_SIZEOF(sig);
622+
sig->loop = loop;
623+
sig->event_type = HEVENT_TYPE_SIGNAL;
624+
// NOTE: use event_id as signo
625+
sig->event_id = signo;
626+
sig->cb = cb;
627+
sig->priority = HEVENT_HIGHEST_PRIORITY;
628+
loop->signals.ptr[signo] = sig;
629+
loop->nsignals++;
630+
}
631+
EVENT_ACTIVE(sig);
632+
s_signal_loop = loop;
633+
signal(signo, signal_handler);
634+
return sig;
635+
}
636+
637+
void hsignal_del(hsignal_t* sig) {
638+
if (!sig->active) return;
639+
hloop_t* loop = sig->loop;
640+
int signo = (int)sig->event_id;
641+
if (signo >= loop->signals.maxsize) return;
642+
loop->signals.ptr[signo] = NULL;
643+
loop->nsignals--;
644+
EVENT_DEL(sig);
645+
}
646+
590647
hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat) {
591648
hidle_t* idle;
592649
HV_ALLOC_SIZEOF(idle);

event/hloop.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@ typedef struct hevent_s hevent_t;
1111

1212
// NOTE: The following structures are subclasses of hevent_t,
1313
// inheriting hevent_t data members and function members.
14+
typedef struct hio_s hio_t;
1415
typedef struct hidle_s hidle_t;
1516
typedef struct htimer_s htimer_t;
1617
typedef struct htimeout_s htimeout_t;
1718
typedef struct hperiod_s hperiod_t;
18-
typedef struct hio_s hio_t;
19+
typedef struct hevent_s hsignal_t;
1920

2021
typedef void (*hevent_cb) (hevent_t* ev);
22+
typedef void (*hio_cb) (hio_t* io);
2123
typedef void (*hidle_cb) (hidle_t* idle);
2224
typedef void (*htimer_cb) (htimer_t* timer);
23-
typedef void (*hio_cb) (hio_t* io);
25+
typedef void (*hsignal_cb) (hsignal_t* sig);
2426

2527
typedef void (*haccept_cb) (hio_t* io);
2628
typedef void (*hconnect_cb) (hio_t* io);
@@ -42,6 +44,7 @@ typedef enum {
4244
HEVENT_TYPE_PERIOD = 0x00000020,
4345
HEVENT_TYPE_TIMER = HEVENT_TYPE_TIMEOUT|HEVENT_TYPE_PERIOD,
4446
HEVENT_TYPE_IDLE = 0x00000100,
47+
HEVENT_TYPE_SIGNAL = 0x00000200,
4548
HEVENT_TYPE_CUSTOM = 0x00000400, // 1024
4649
} hevent_type_e;
4750

@@ -184,6 +187,10 @@ HV_EXPORT void* hloop_userdata(hloop_t* loop);
184187
// NOTE: hloop_post_event is thread-safe, used to post event from other thread to loop thread.
185188
HV_EXPORT void hloop_post_event(hloop_t* loop, hevent_t* ev);
186189

190+
// signal
191+
HV_EXPORT hsignal_t* hsignal_add(hloop_t* loop, hsignal_cb cb, int signo);
192+
HV_EXPORT void hsignal_del(hsignal_t* sig);
193+
187194
// idle
188195
HV_EXPORT hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
189196
HV_EXPORT void hidle_del(hidle_t* idle);

examples/hloop_test.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ void on_custom_events(hevent_t* ev) {
6464
printf("on_custom_events event_type=%d userdata=%ld\n", (int)ev->event_type, (long)(intptr_t)ev->userdata);
6565
}
6666

67+
void on_signal(hsignal_t* sig) {
68+
printf("on_signal signo=%d\n", (int)hevent_id(sig));
69+
hloop_stop(hevent_loop(sig));
70+
}
71+
6772
int main() {
6873
// memcheck atexit
6974
HV_MEMCHECK;
@@ -87,6 +92,9 @@ int main() {
8792
htimer_add_period(loop, cron_minutely, -1, -1, -1, -1, -1, INFINITE);
8893
htimer_add_period(loop, cron_hourly, minute+1, -1, -1, -1, -1, INFINITE);
8994

95+
// test signal: enter Ctrl-C to trigger
96+
hsignal_add(loop, on_signal, SIGINT);
97+
9098
// test network_logger
9199
htimer_add(loop, timer_write_log, 1000, INFINITE);
92100
hlog_set_handler(mylogger);

0 commit comments

Comments
 (0)