Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: support socket in some block phase #1825

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
13 changes: 13 additions & 0 deletions config
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,18 @@ HTTP_LUA_SRCS=" \
$ngx_addon_dir/src/ngx_http_lua_worker_thread.c \
"

if echo "$EVENT_MODULES" | grep ngx_epoll_module 2>&1 >/dev/null; then
HTTP_LUA_SRCS="$HTTP_LUA_SRCS $ngx_addon_dir/src/event/ngx_http_lua_epoll.c"
fi

if echo "$EVENT_MODULES" | grep ngx_poll_module 2>&1 >/dev/null; then
HTTP_LUA_SRCS="$HTTP_LUA_SRCS $ngx_addon_dir/src/event/ngx_http_lua_poll.c"
fi

if echo "$EVENT_MODULES" | grep ngx_kqueue_module 2>&1 >/dev/null; then
HTTP_LUA_SRCS="$HTTP_LUA_SRCS $ngx_addon_dir/src/event/ngx_http_lua_kqueue.c"
fi

HTTP_LUA_DEPS=" \
$ngx_addon_dir/src/ddebug.h \
$ngx_addon_dir/src/ngx_http_lua_autoconf.h \
Expand Down Expand Up @@ -359,6 +371,7 @@ HTTP_LUA_DEPS=" \
$ngx_addon_dir/src/ngx_http_lua_input_filters.h \
$ngx_addon_dir/src/ngx_http_lua_pipe.h \
$ngx_addon_dir/src/ngx_http_lua_worker_thread.h \
$ngx_addon_dir/src/ngx_http_lua_event.h \
"

# ----------------------------------------
Expand Down
211 changes: 211 additions & 0 deletions src/event/ngx_http_lua_epoll.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@

/*
* Copyright (C) Yichun Zhang (agentzh)
*/


#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_http.h>
#include "../ngx_http_lua_event.h"


static ngx_int_t ngx_http_lua_epoll_init_event(ngx_cycle_t *cycle);
static ngx_int_t ngx_http_lua_epoll_set_event(ngx_event_t *ev, ngx_int_t event);
static ngx_int_t ngx_http_lua_epoll_clear_event(ngx_event_t *ev,
ngx_int_t event);
static ngx_int_t ngx_http_lua_epoll_process_event(ngx_http_request_t *r,
ngx_msec_t timer);

static int epoll_created = -1;

ngx_http_lua_event_actions_t ngx_http_lua_epoll = {
ngx_http_lua_epoll_init_event,
ngx_http_lua_epoll_set_event,
ngx_http_lua_epoll_clear_event,
ngx_http_lua_epoll_process_event,
};


static ngx_int_t
ngx_http_lua_epoll_init_event(ngx_cycle_t *cycle)
{
epoll_created = epoll_create(1);

if (epoll_created == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"lua epoll_create() failed");

return NGX_ERROR;
}

return NGX_OK;
}


static ngx_int_t
ngx_http_lua_epoll_set_event(ngx_event_t *ev, ngx_int_t event)
{
int op;
uint32_t events, prev;
ngx_connection_t *c;
ngx_event_t *e;
struct epoll_event ee;

c = ev->data;

events = (uint32_t) event;

if (event == NGX_READ_EVENT) {
e = c->write;
prev = EPOLLOUT;
#if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP)
events = EPOLLIN|EPOLLRDHUP;
#endif

} else {
e = c->read;
prev = EPOLLIN|EPOLLRDHUP;
#if (NGX_WRITE_EVENT != EPOLLOUT)
events = EPOLLOUT;
#endif
}

if (e->active) {
op = EPOLL_CTL_MOD;
events |= prev;

} else {
op = EPOLL_CTL_ADD;
}

ee.events = events;
ee.data.ptr = c;

if (epoll_ctl(epoll_created, op, c->fd, &ee) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"lua epoll_ctl(EPOLL_CTL_ADD, %d) failed, add event: %d",
c->fd, events);

return NGX_ERROR;
}

ev->active = 1;

return NGX_OK;
}


static ngx_int_t
ngx_http_lua_epoll_clear_event(ngx_event_t *ev, ngx_int_t event)
{
ngx_event_t *e;
ngx_connection_t *c;
int op;
uint32_t prev;
struct epoll_event ee;

c = ev->data;

if (event == NGX_READ_EVENT) {
e = c->write;
prev = EPOLLOUT;

} else {
e = c->read;
prev = EPOLLIN|EPOLLRDHUP;
}

if (e->active) {
op = EPOLL_CTL_MOD;
ee.events = prev;
ee.data.ptr = c;

} else {
op = EPOLL_CTL_DEL;
ee.events = 0;
ee.data.ptr = NULL;
}

if (epoll_ctl(epoll_created, op, c->fd, &ee) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"lua epoll_ctl(EPOLL_CTL_DEL, %d) failed", c->fd);

return NGX_ERROR;
}

ev->active = 0;

return NGX_OK;
}


static ngx_int_t
ngx_http_lua_epoll_process_event(ngx_http_request_t *r, ngx_msec_t timer)
{
int events;
uint32_t revents;
ngx_err_t err;
ngx_event_t *rev, *wev;
ngx_connection_t *c;
struct epoll_event ee;

events = epoll_wait(epoll_created, &ee, 1, timer);

err = (events == -1) ? ngx_errno : 0;

if (err) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
"lua epoll_wait() failed");

return NGX_ERROR;
}

if (events == 0) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
if (timer != NGX_TIMER_INFINITE) {
return NGX_OK;
}
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,

"lua epoll_wait() returned no events without timeout");

return NGX_ERROR;
}

c = ee.data.ptr;
revents = ee.events;

if (revents & (EPOLLERR|EPOLLHUP)) {
ngx_log_debug2(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
"epoll_wait() error on fd:%d ev:%04XD",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"epoll_wait() error on fd:%d ev:%04XD",
"lua epoll_wait() error on fd:%d ev:%04XD",

c->fd, revents);

/*
* if the error events were returned, add EPOLLIN and EPOLLOUT
* to handle the events at least in one active handler
*/

revents |= EPOLLIN|EPOLLOUT;
}

rev = c->read;

if ((revents & EPOLLIN) && rev->active) {

#if (NGX_HAVE_EPOLLRDHUP)
if (revents & EPOLLRDHUP) {
rev->pending_eof = 1;
}
#endif

rev->ready = 1;
rev->available = -1;
}

wev = c->write;

if ((revents & EPOLLOUT) && wev->active) {
wev->ready = 1;
#if (NGX_THREADS)
wev->complete = 1;
#endif
}

return NGX_OK;
}
139 changes: 139 additions & 0 deletions src/event/ngx_http_lua_kqueue.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@

/*
* Copyright (C) Yichun Zhang (agentzh)
*/


#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_http.h>
#include "../ngx_http_lua_event.h"


static ngx_int_t ngx_http_lua_kqueue_init_event(ngx_cycle_t *cycle);
static ngx_int_t ngx_http_lua_kqueue_set_event(ngx_event_t *ev,
ngx_int_t event);
static ngx_int_t ngx_http_lua_kqueue_clear_event(ngx_event_t *ev,
ngx_int_t event);
static ngx_int_t ngx_http_lua_kqueue_process_event(ngx_http_request_t *r,
ngx_msec_t timer);

int kq = -1;
static struct kevent kch[2];
static ngx_uint_t nchanges;

ngx_http_lua_event_actions_t ngx_http_lua_kqueue = {
ngx_http_lua_kqueue_init_event,
ngx_http_lua_kqueue_set_event,
ngx_http_lua_kqueue_clear_event,
ngx_http_lua_kqueue_process_event,
};


static ngx_int_t
ngx_http_lua_kqueue_init_event(ngx_cycle_t *cycle)
{
nchanges = 0;
kq = kqueue();

if (kq == -1) {
ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
"lua kqueue() failed");

return NGX_ERROR;
}

return NGX_OK;
}


static ngx_int_t
ngx_http_lua_kqueue_set_event(ngx_event_t *ev, ngx_int_t event)
{
ngx_connection_t *c;

c = ev->data;

ev->active = 1;

kch[nchanges].ident = c->fd;
kch[nchanges].filter = (short) event;
kch[nchanges].flags = EV_ADD|EV_ENABLE;
kch[nchanges].udata = NGX_KQUEUE_UDATA_T (ev);

nchanges++;

return NGX_OK;
}


static ngx_int_t
ngx_http_lua_kqueue_clear_event(ngx_event_t *ev, ngx_int_t event)
{
ngx_connection_t *c;

c = ev->data;

ev->active = 0;

kch[0].ident = c->fd;
kch[0].filter = (short) event;
kch[0].flags = EV_DELETE;
kch[0].udata = NGX_KQUEUE_UDATA_T (ev);

if (kevent(kq, kch, 1, NULL, 0, NULL) == -1) {
ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
"lua kevent() failed");

return NGX_ERROR;
}

return NGX_OK;
}


static ngx_int_t
ngx_http_lua_kqueue_process_event(ngx_http_request_t *r, ngx_msec_t timer)
{
int events;
struct timespec ts;
ngx_event_t *ev;
ngx_err_t err;
struct kevent kev;

ts.tv_sec = timer / 1000;
ts.tv_nsec = (timer % 1000) * 1000000;

events = kevent(kq, kch, nchanges, &kev, 1, &ts);

nchanges = 0;
err = (events == -1) ? ngx_errno : 0;

if (err) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
"lua kevent() failed");

return NGX_ERROR;
}

if (events == 0) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
if (timer != NGX_TIMER_INFINITE) {
return NGX_OK;
}
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,

"lua kevent() returned no events without timeout");

return NGX_ERROR;
}

ev = (ngx_event_t *) kev.udata;

ev->available = kev.data;
ev->ready = 1;

if (kev.flags & EV_EOF) {
ev->pending_eof = 1;

ngx_log_error(NGX_LOG_ALERT, r->connection->log, kev.fflags,
"lua kevent() reported that connect() failed");
}

return NGX_OK;
}
Loading