Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit cf8a31d

Browse files
committedNov 9, 2020
feature: support socket in some block phase
1 parent fdf752d commit cf8a31d

File tree

5 files changed

+291
-5
lines changed

5 files changed

+291
-5
lines changed
 

‎config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ HTTP_LUA_SRCS=" \
296296
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.c \
297297
$ngx_addon_dir/src/ngx_http_lua_input_filters.c \
298298
$ngx_addon_dir/src/ngx_http_lua_pipe.c \
299+
$ngx_addon_dir/src/event/ngx_http_lua_kqueue.c \
299300
"
300301

301302
HTTP_LUA_DEPS=" \
@@ -355,6 +356,7 @@ HTTP_LUA_DEPS=" \
355356
$ngx_addon_dir/src/ngx_http_lua_log_ringbuf.h \
356357
$ngx_addon_dir/src/ngx_http_lua_input_filters.h \
357358
$ngx_addon_dir/src/ngx_http_lua_pipe.h \
359+
$ngx_addon_dir/src/ngx_http_lua_event.h \
358360
"
359361

360362
# ----------------------------------------

‎src/event/ngx_http_lua_kqueue.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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+
11+
int ngx_lua_kqueue = -1;
12+
struct kevent change_list[1];
13+
struct kevent event_list[1];
14+
15+
ngx_int_t
16+
ngx_http_lua_kqueue_init(ngx_conf_t *cf)
17+
{
18+
if (ngx_lua_kqueue == -1) {
19+
ngx_lua_kqueue = kqueue();
20+
21+
if (ngx_lua_kqueue == -1) {
22+
ngx_conf_log_error(NGX_LOG_ALERT, cf, 0, "kqueue() failed");
23+
24+
return NGX_ERROR;
25+
}
26+
}
27+
28+
return NGX_OK;
29+
}
30+
31+
32+
void
33+
ngx_http_lua_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter)
34+
{
35+
struct kevent *kev;
36+
ngx_connection_t *c;
37+
38+
c = ev->data;
39+
40+
kev = &change_list[0];
41+
42+
kev->ident = c->fd;
43+
kev->filter = (short) filter;
44+
kev->flags = EV_ADD|EV_ENABLE;
45+
kev->udata = NGX_KQUEUE_UDATA_T ((uintptr_t) ev | ev->instance);
46+
}
47+
48+
49+
ngx_int_t
50+
ngx_http_lua_kqueue_process_events(ngx_http_request_t *r, ngx_msec_t timer)
51+
{
52+
int events;
53+
struct timespec ts;
54+
ngx_event_t *ev;
55+
ngx_int_t instance;
56+
ngx_err_t err;
57+
58+
ts.tv_sec = timer / 1000;
59+
ts.tv_nsec = (timer % 1000) * 1000000;
60+
61+
events = kevent(ngx_lua_kqueue, change_list, 1, event_list, 1, &ts);
62+
63+
err = (events == -1) ? ngx_errno : 0;
64+
65+
if (err) {
66+
ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
67+
"kevent() failed");
68+
69+
return NGX_ERROR;
70+
}
71+
72+
if (events == 0) {
73+
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
74+
"kevent() returned no events without timeout");
75+
76+
return NGX_ERROR;
77+
}
78+
79+
ev = (ngx_event_t *) event_list[0].udata;
80+
instance = (uintptr_t) ev & 1;
81+
ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1);
82+
83+
ev->available = event_list[0].data;
84+
ev->ready = 1;
85+
86+
return NGX_OK;
87+
}

‎src/ngx_http_lua_event.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
/*
3+
* Copyright (C) Yichun Zhang (agentzh)
4+
*/
5+
6+
7+
#ifndef _NGX_HTTP_LUA_EVENT_H_INCLUDED_
8+
#define _NGX_HTTP_LUA_EVENT_H_INCLUDED_
9+
10+
11+
#include "ngx_http_lua_common.h"
12+
13+
14+
ngx_int_t ngx_http_lua_kqueue_init(ngx_conf_t *cf);
15+
16+
void ngx_http_lua_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter);
17+
18+
ngx_int_t ngx_http_lua_kqueue_process_events(ngx_http_request_t *r,
19+
ngx_msec_t timer);
20+
21+
22+
#endif /* _NGX_HTTP_LUA_EVENT_H_INCLUDED_ */
23+
24+
/* vi:set ft=c ts=4 sw=4 et fdm=marker: */

‎src/ngx_http_lua_module.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "ngx_http_lua_ssl_session_fetchby.h"
3232
#include "ngx_http_lua_headers.h"
3333
#include "ngx_http_lua_pipe.h"
34+
#include "ngx_http_lua_event.h"
3435

3536

3637
static void *ngx_http_lua_create_main_conf(ngx_conf_t *cf);
@@ -786,6 +787,11 @@ ngx_http_lua_init(ngx_conf_t *cf)
786787
cln->handler = ngx_http_lua_ngx_raw_header_cleanup;
787788
#endif
788789

790+
rc = ngx_http_lua_kqueue_init(cf);
791+
if (rc == NGX_ERROR) {
792+
return rc;
793+
}
794+
789795
if (lmcf->lua == NULL) {
790796
dd("initializing lua vm");
791797

‎src/ngx_http_lua_socket_tcp.c

Lines changed: 172 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "ngx_http_lua_output.h"
1818
#include "ngx_http_lua_contentby.h"
1919
#include "ngx_http_lua_probe.h"
20+
#include "ngx_http_lua_event.h"
2021

2122

2223
static int ngx_http_lua_socket_tcp(lua_State *L);
@@ -159,6 +160,12 @@ static void ngx_http_lua_ssl_handshake_handler(ngx_connection_t *c);
159160
static int ngx_http_lua_ssl_free_session(lua_State *L);
160161
#endif
161162
static void ngx_http_lua_socket_tcp_close_connection(ngx_connection_t *c);
163+
static ngx_int_t ngx_http_lua_socket_tcp_block_conn(ngx_http_request_t *r,
164+
ngx_http_lua_socket_tcp_upstream_t *u);
165+
static ngx_int_t ngx_http_lua_socket_tcp_block_write(ngx_http_request_t *r,
166+
ngx_http_lua_socket_tcp_upstream_t *u);
167+
static ngx_int_t ngx_http_lua_socket_tcp_block_read(ngx_http_request_t *r,
168+
ngx_http_lua_socket_tcp_upstream_t *u);
162169

163170

164171
enum {
@@ -446,7 +453,7 @@ ngx_http_lua_socket_tcp(lua_State *L)
446453
return luaL_error(L, "no ctx found");
447454
}
448455

449-
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_YIELDABLE);
456+
/* ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_YIELDABLE); */
450457

451458
lua_createtable(L, 5 /* narr */, 1 /* nrec */);
452459
lua_pushlightuserdata(L, ngx_http_lua_lightudata_mask(
@@ -888,7 +895,7 @@ ngx_http_lua_socket_tcp_connect(lua_State *L)
888895
return luaL_error(L, "no ctx found");
889896
}
890897

891-
ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_YIELDABLE);
898+
/* ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_YIELDABLE); */
892899

893900
luaL_checktype(L, 1, LUA_TTABLE);
894901

@@ -1477,11 +1484,16 @@ ngx_http_lua_socket_resolve_retval_handler(ngx_http_request_t *r,
14771484
u->writer.last = &u->writer.out;
14781485
#endif
14791486

1480-
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
1487+
dd("setting data to %p", u);
14811488

1482-
coctx = ctx->cur_co_ctx;
1489+
ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
14831490

1484-
dd("setting data to %p", u);
1491+
if (rc == NGX_AGAIN && !(ctx->context & NGX_HTTP_LUA_CONTEXT_YIELDABLE)) {
1492+
rc = ngx_http_lua_socket_tcp_block_conn(r, u);
1493+
if (rc == NGX_ERROR) {
1494+
return ngx_http_lua_socket_conn_error_retval_handler(r, u, L);
1495+
}
1496+
}
14851497

14861498
if (rc == NGX_OK) {
14871499
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1517,6 +1529,8 @@ ngx_http_lua_socket_resolve_retval_handler(ngx_http_request_t *r,
15171529

15181530
/* rc == NGX_AGAIN */
15191531

1532+
coctx = ctx->cur_co_ctx;
1533+
15201534
ngx_http_lua_cleanup_pending_operation(coctx);
15211535
coctx->cleanup = ngx_http_lua_coctx_cleanup;
15221536
coctx->data = u;
@@ -1780,6 +1794,10 @@ ngx_http_lua_socket_tcp_sslhandshake(lua_State *L)
17801794

17811795
dd("ngx_ssl_handshake returned %d", (int) rc);
17821796

1797+
if (rc == NGX_AGAIN && !(ctx->context & NGX_HTTP_LUA_CONTEXT_YIELDABLE)) {
1798+
/* Do something */
1799+
}
1800+
17831801
if (rc == NGX_AGAIN) {
17841802
if (c->write->timer_set) {
17851803
ngx_del_timer(c->write);
@@ -2105,6 +2123,10 @@ ngx_http_lua_socket_tcp_receive_helper(ngx_http_request_t *r,
21052123

21062124
rc = ngx_http_lua_socket_tcp_read(r, u);
21072125

2126+
if (rc == NGX_AGAIN && !(ctx->context & NGX_HTTP_LUA_CONTEXT_YIELDABLE)) {
2127+
rc = ngx_http_lua_socket_tcp_block_read(r, u);
2128+
}
2129+
21082130
if (rc == NGX_ERROR) {
21092131
dd("read failed: %d", (int) u->ft_type);
21102132
rc = ngx_http_lua_socket_tcp_receive_retval_handler(r, u, L);
@@ -2917,6 +2939,10 @@ ngx_http_lua_socket_tcp_send(lua_State *L)
29172939

29182940
dd("socket send returned %d", (int) rc);
29192941

2942+
if (rc == NGX_AGAIN && !(ctx->context & NGX_HTTP_LUA_CONTEXT_YIELDABLE)) {
2943+
rc = ngx_http_lua_socket_tcp_block_write(r, u);
2944+
}
2945+
29202946
if (rc == NGX_ERROR) {
29212947
return ngx_http_lua_socket_write_error_retval_handler(r, u, L);
29222948
}
@@ -4499,6 +4525,10 @@ ngx_http_lua_socket_receiveuntil_iterator(lua_State *L)
44994525

45004526
rc = ngx_http_lua_socket_tcp_read(r, u);
45014527

4528+
if (rc == NGX_AGAIN && !(ctx->context & NGX_HTTP_LUA_CONTEXT_YIELDABLE)) {
4529+
rc = ngx_http_lua_socket_tcp_block_read(r, u);
4530+
}
4531+
45024532
if (rc == NGX_ERROR) {
45034533
dd("read failed: %d", (int) u->ft_type);
45044534
rc = ngx_http_lua_socket_tcp_receive_retval_handler(r, u, L);
@@ -6115,6 +6145,143 @@ ngx_http_lua_coctx_cleanup(void *data)
61156145
}
61166146

61176147

6148+
static ngx_int_t
6149+
ngx_http_lua_socket_tcp_block_conn(ngx_http_request_t *r,
6150+
ngx_http_lua_socket_tcp_upstream_t *u)
6151+
{
6152+
ngx_int_t rc;
6153+
ngx_msec_t delta;
6154+
ngx_connection_t *c = u->peer.connection;
6155+
ngx_msec_t timer = u->connect_timeout;
6156+
6157+
ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
6158+
ngx_http_lua_kqueue_set_event(c->write, NGX_WRITE_EVENT);
6159+
6160+
delta = ngx_current_msec;
6161+
6162+
rc = ngx_http_lua_kqueue_process_events(r, timer);
6163+
6164+
if (rc == NGX_ERROR) {
6165+
ngx_http_lua_socket_handle_conn_error(r, u,
6166+
NGX_HTTP_LUA_SOCKET_FT_ERROR);
6167+
6168+
return rc;
6169+
}
6170+
6171+
ngx_time_update();
6172+
6173+
if (ngx_current_msec - delta >= timer) {
6174+
ngx_http_lua_socket_handle_conn_error(r, u,
6175+
NGX_HTTP_LUA_SOCKET_FT_TIMEOUT);
6176+
6177+
return NGX_ERROR;
6178+
}
6179+
6180+
return NGX_OK;
6181+
}
6182+
6183+
6184+
static ngx_int_t
6185+
ngx_http_lua_socket_tcp_block_write(ngx_http_request_t *r,
6186+
ngx_http_lua_socket_tcp_upstream_t *u)
6187+
{
6188+
int rc;
6189+
ngx_msec_t delta;
6190+
ngx_connection_t *c = u->peer.connection;
6191+
ngx_msec_t timer = u->connect_timeout;
6192+
6193+
ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
6194+
ngx_http_lua_kqueue_set_event(c->write, NGX_WRITE_EVENT);
6195+
6196+
delta = ngx_current_msec;
6197+
6198+
rc = ngx_http_lua_kqueue_process_events(r, timer);
6199+
6200+
if (rc == NGX_ERROR) {
6201+
ngx_http_lua_socket_handle_write_error(r, u,
6202+
NGX_HTTP_LUA_SOCKET_FT_ERROR);
6203+
6204+
return rc;
6205+
}
6206+
6207+
ngx_time_update();
6208+
6209+
if (ngx_current_msec - delta >= timer) {
6210+
ngx_http_lua_socket_handle_write_error(r, u,
6211+
NGX_HTTP_LUA_SOCKET_FT_TIMEOUT);
6212+
6213+
return NGX_ERROR;
6214+
}
6215+
6216+
return NGX_OK;
6217+
}
6218+
6219+
6220+
static ngx_int_t
6221+
ngx_http_lua_socket_tcp_block_read(ngx_http_request_t *r,
6222+
ngx_http_lua_socket_tcp_upstream_t *u)
6223+
{
6224+
int rc;
6225+
ngx_msec_t delta;
6226+
ngx_event_t *rev;
6227+
ngx_connection_t *c = u->peer.connection;
6228+
ngx_msec_t timer = u->connect_timeout;
6229+
6230+
ngx_http_lua_kqueue_set_event(c->read, NGX_READ_EVENT);
6231+
6232+
delta = ngx_current_msec;
6233+
6234+
for (;;) {
6235+
6236+
ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
6237+
6238+
if (c->read->timer_set) {
6239+
ngx_del_timer(c->read);
6240+
}
6241+
6242+
rc = ngx_http_lua_kqueue_process_events(r, timer);
6243+
if (rc == NGX_ERROR) {
6244+
ngx_http_lua_socket_handle_read_error(r, u,
6245+
NGX_HTTP_LUA_SOCKET_FT_ERROR);
6246+
6247+
return rc;
6248+
}
6249+
6250+
ngx_time_update();
6251+
6252+
/* timeout */
6253+
if (ngx_current_msec - delta >= timer) {
6254+
ngx_http_lua_socket_handle_read_error(r, u,
6255+
NGX_HTTP_LUA_SOCKET_FT_TIMEOUT);
6256+
6257+
return NGX_ERROR;
6258+
}
6259+
6260+
timer -= ngx_current_msec - delta;
6261+
6262+
if (u->buffer.start != NULL) {
6263+
rev = c->read;
6264+
6265+
rev->ready = 1;
6266+
#if (NGX_HAVE_KQUEUE || NGX_HAVE_EPOLLRDHUP)
6267+
rev->available = 1;
6268+
#endif
6269+
6270+
rc = ngx_http_lua_socket_tcp_read(r, u);
6271+
6272+
if (rc == NGX_ERROR || rc == NGX_OK) {
6273+
return rc;
6274+
}
6275+
6276+
/* NGX_AGAIN, continue in loop*/
6277+
}
6278+
}
6279+
6280+
/* unreachable */
6281+
return NGX_ERROR;
6282+
}
6283+
6284+
61186285
#if (NGX_HTTP_SSL)
61196286

61206287
static int

0 commit comments

Comments
 (0)
Please sign in to comment.