Skip to content

Commit 7b2ce35

Browse files
committed
feature: support socket in some block phase
1 parent fdf752d commit 7b2ce35

8 files changed

+729
-5
lines changed

config

+13
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,18 @@ HTTP_LUA_SRCS=" \
298298
$ngx_addon_dir/src/ngx_http_lua_pipe.c \
299299
"
300300

301+
if [ $EVENT_MODULES =~ "ngx_epoll_module" ]; then
302+
HTTP_LUA_SRCS="$HTTP_LUA_SRCS $ngx_addon_dir/src/event/ngx_http_lua_poll.c"
303+
fi
304+
305+
if [ $EVENT_MODULES =~ "ngx_poll_module" ]; then
306+
HTTP_LUA_SRCS="$HTTP_LUA_SRCS $ngx_addon_dir/src/event/ngx_http_lua_poll.c"
307+
fi
308+
309+
if [ $EVENT_MODULES =~ "ngx_kqueue_module" ]; then
310+
HTTP_LUA_SRCS="$HTTP_LUA_SRCS $ngx_addon_dir/src/event/ngx_http_lua_kqueue.c"
311+
fi
312+
301313
HTTP_LUA_DEPS=" \
302314
$ngx_addon_dir/src/ddebug.h \
303315
$ngx_addon_dir/src/ngx_http_lua_autoconf.h \
@@ -355,6 +367,7 @@ HTTP_LUA_DEPS=" \
355367
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.h \
356368
$ngx_addon_dir/src/ngx_http_lua_input_filters.h \
357369
$ngx_addon_dir/src/ngx_http_lua_pipe.h \
370+
$ngx_addon_dir/src/ngx_http_lua_event.h \
358371
"
359372

360373
# ----------------------------------------

src/event/ngx_http_lua_epoll.c

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
2+
/*
3+
* Copyright (C) Yichun Zhang (agentzh)
4+
*/
5+
6+
7+
#include <ngx_core.h>
8+
#include <ngx_event.h>
9+
#include <ngx_http.h>
10+
#include "../ngx_http_lua_event.h"
11+
12+
13+
static ngx_int_t ngx_http_lua_epoll_init_event(ngx_conf_t *cf);
14+
15+
static void ngx_http_lua_epoll_set_event(ngx_event_t *ev, ngx_int_t event);
16+
17+
static ngx_int_t ngx_http_lua_epoll_process_events(ngx_http_request_t *r,
18+
ngx_msec_t timer);
19+
20+
static int ep = -1;
21+
static struct epoll_event event_list[1];
22+
23+
ngx_http_lua_event_actions_t ngx_http_lua_epoll = {
24+
ngx_http_lua_epoll_init_event,
25+
ngx_http_lua_epoll_set_event,
26+
ngx_http_lua_epoll_process_events,
27+
};
28+
29+
30+
static ngx_int_t
31+
ngx_http_lua_epoll_init_event(ngx_conf_t *cf)
32+
{
33+
ep = epoll_create(cycle->connection_n / 2);
34+
35+
if (ep == -1) {
36+
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
37+
"epoll_create() failed");
38+
return NGX_ERROR;
39+
}
40+
41+
return NGX_OK;
42+
}
43+
44+
45+
static void
46+
ngx_http_lua_epoll_set_event(ngx_event_t *ev, ngx_int_t event)
47+
{
48+
int op;
49+
uint32_t events, prev;
50+
ngx_event_t *e;
51+
ngx_connection_t *c;
52+
struct epoll_event ee;
53+
54+
c = ev->data;
55+
56+
events = (uint32_t) event;
57+
58+
if (event == NGX_READ_EVENT) {
59+
e = c->write;
60+
prev = EPOLLOUT;
61+
#if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP)
62+
events = EPOLLIN|EPOLLRDHUP;
63+
#endif
64+
65+
} else {
66+
e = c->read;
67+
prev = EPOLLIN|EPOLLRDHUP;
68+
#if (NGX_WRITE_EVENT != EPOLLOUT)
69+
events = EPOLLOUT;
70+
#endif
71+
}
72+
73+
if (e->active) {
74+
op = EPOLL_CTL_MOD;
75+
events |= prev;
76+
77+
} else {
78+
op = EPOLL_CTL_ADD;
79+
}
80+
81+
#if (NGX_HAVE_EPOLLEXCLUSIVE && NGX_HAVE_EPOLLRDHUP)
82+
if (flags & NGX_EXCLUSIVE_EVENT) {
83+
events &= ~EPOLLRDHUP;
84+
}
85+
#endif
86+
87+
ee.events = events | (uint32_t) flags;
88+
ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);
89+
90+
if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
91+
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
92+
"epoll_ctl(%d, %d) failed", op, c->fd);
93+
return NGX_ERROR;
94+
}
95+
96+
ev->active = 1;
97+
98+
return NGX_OK;
99+
}
100+
101+
102+
static ngx_int_t
103+
ngx_http_lua_epoll_process_events(ngx_http_request_t *r, ngx_msec_t timer)
104+
{
105+
int events;
106+
uint32_t revents;
107+
ngx_int_t instance, i;
108+
ngx_uint_t level;
109+
ngx_err_t err;
110+
ngx_event_t *rev, *wev;
111+
ngx_queue_t *queue;
112+
ngx_connection_t *c;
113+
114+
events = epoll_wait(ep, event_list, (int) nevents, timer);
115+
116+
err = (events == -1) ? ngx_errno : 0;
117+
118+
if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
119+
ngx_time_update();
120+
}
121+
122+
if (err) {
123+
ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
124+
"epoll_wait() failed");
125+
126+
return NGX_ERROR;
127+
}
128+
129+
if (events == 0) {
130+
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
131+
"epoll_wait() returned no events without timeout");
132+
133+
return NGX_ERROR;
134+
}
135+
136+
c = event_list[0].data.ptr;
137+
138+
instance = (uintptr_t) c & 1;
139+
c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
140+
141+
revents = event_list[0].events;
142+
143+
if (revents & (EPOLLERR|EPOLLHUP)) {
144+
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
145+
"epoll_wait() error on fd:%d ev:%04XD",
146+
c->fd, revents);
147+
148+
/*
149+
* if the error events were returned, add EPOLLIN and EPOLLOUT
150+
* to handle the events at least in one active handler
151+
*/
152+
153+
revents |= EPOLLIN|EPOLLOUT;
154+
}
155+
156+
rev = c->read;
157+
158+
if ((revents & EPOLLIN) && rev->active) {
159+
160+
#if (NGX_HAVE_EPOLLRDHUP)
161+
if (revents & EPOLLRDHUP) {
162+
rev->pending_eof = 1;
163+
}
164+
#endif
165+
166+
rev->ready = 1;
167+
rev->available = -1;
168+
}
169+
170+
wev = c->write;
171+
172+
if ((revents & EPOLLOUT) && wev->active) {
173+
wev->ready = 1;
174+
#if (NGX_THREADS)
175+
wev->complete = 1;
176+
#endif
177+
}
178+
179+
return NGX_OK;
180+
}

src/event/ngx_http_lua_kqueue.c

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
2+
/*
3+
* Copyright (C) Yichun Zhang (agentzh)
4+
*/
5+
6+
7+
#include <ngx_core.h>
8+
#include <ngx_event.h>
9+
#include <ngx_http.h>
10+
#include "../ngx_http_lua_event.h"
11+
12+
13+
static ngx_int_t ngx_http_lua_kqueue_init_event(ngx_conf_t *cf);
14+
15+
static void ngx_http_lua_kqueue_set_event(ngx_event_t *ev, ngx_int_t event);
16+
17+
static ngx_int_t ngx_http_lua_kqueue_process_events(ngx_http_request_t *r,
18+
ngx_msec_t timer);
19+
20+
int ngx_lua_kqueue = -1;
21+
static struct kevent change_list[1];
22+
static struct kevent event_list[1];
23+
24+
ngx_http_lua_event_actions_t ngx_http_lua_kqueue = {
25+
ngx_http_lua_kqueue_init_event,
26+
ngx_http_lua_kqueue_set_event,
27+
ngx_http_lua_kqueue_process_events,
28+
};
29+
30+
31+
static ngx_int_t
32+
ngx_http_lua_kqueue_init_event(ngx_conf_t *cf)
33+
{
34+
if (ngx_lua_kqueue == -1) {
35+
ngx_lua_kqueue = kqueue();
36+
37+
if (ngx_lua_kqueue == -1) {
38+
ngx_conf_log_error(NGX_LOG_ALERT, cf, 0, "kqueue() failed");
39+
40+
return NGX_ERROR;
41+
}
42+
}
43+
44+
return NGX_OK;
45+
}
46+
47+
48+
static void
49+
ngx_http_lua_kqueue_set_event(ngx_event_t *ev, ngx_int_t event)
50+
{
51+
struct kevent *kev;
52+
ngx_connection_t *c;
53+
54+
c = ev->data;
55+
56+
ev->active = 1;
57+
58+
kev = &change_list[0];
59+
60+
kev->ident = c->fd;
61+
kev->filter = (short) event;
62+
kev->flags = EV_ADD|EV_ENABLE;
63+
kev->udata = NGX_KQUEUE_UDATA_T ((uintptr_t) ev | ev->instance);
64+
}
65+
66+
67+
static ngx_int_t
68+
ngx_http_lua_kqueue_process_events(ngx_http_request_t *r, ngx_msec_t timer)
69+
{
70+
int events;
71+
struct timespec ts;
72+
ngx_event_t *ev;
73+
ngx_int_t instance;
74+
ngx_err_t err;
75+
76+
ts.tv_sec = timer / 1000;
77+
ts.tv_nsec = (timer % 1000) * 1000000;
78+
79+
events = kevent(ngx_lua_kqueue, change_list, 1, event_list, 1, &ts);
80+
81+
err = (events == -1) ? ngx_errno : 0;
82+
83+
if (err) {
84+
ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
85+
"kevent() failed");
86+
87+
return NGX_ERROR;
88+
}
89+
90+
if (events == 0) {
91+
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
92+
"kevent() returned no events without timeout");
93+
94+
return NGX_ERROR;
95+
}
96+
97+
ev = (ngx_event_t *) event_list[0].udata;
98+
instance = (uintptr_t) ev & 1;
99+
ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1);
100+
101+
ev->available = event_list[0].data;
102+
103+
if (event_list[0].flags & EV_EOF) {
104+
ev->pending_eof = 1;
105+
}
106+
107+
ev->ready = 1;
108+
109+
return NGX_OK;
110+
}

0 commit comments

Comments
 (0)