*/
static void hlua_socket_release(struct appctx *appctx)
{
+ struct xref *peer;
+
/* Remove my link in the original object. */
- xref_disconnect(&appctx->ctx.hlua_cosocket.xref);
+ peer = xref_get_peer_and_lock(&appctx->ctx.hlua_cosocket.xref);
+ if (peer)
+ xref_disconnect(&appctx->ctx.hlua_cosocket.xref, peer);
/* Wake all the task waiting for me. */
notification_wake(&appctx->ctx.hlua_cosocket.wake_on_read);
MAY_LJMP(check_args(L, 1, "__gc"));
socket = MAY_LJMP(hlua_checksocket(L, 1));
- peer = xref_get_peer(&socket->xref);
- if (!peer) {
- xref_disconnect(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
+ if (!peer)
return 0;
- }
appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
/* Set the flag which destroy the session. */
appctx_wakeup(appctx);
/* Remove all reference between the Lua stack and the coroutine stream. */
- xref_disconnect(&socket->xref);
+ xref_disconnect(&socket->xref, peer);
return 0;
}
if (socket->tid != tid)
WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
- peer = xref_get_peer(&socket->xref);
- if (!peer) {
- xref_disconnect(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
+ if (!peer)
return 0;
- }
appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
/* Set the flag which destroy the session. */
appctx_wakeup(appctx);
/* Remove all reference between the Lua stack and the coroutine stream. */
- xref_disconnect(&socket->xref);
+ xref_disconnect(&socket->xref, peer);
return 0;
}
WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
/* check for connection break. If some data where read, return it. */
- peer = xref_get_peer(&socket->xref);
- if (!peer) {
- xref_disconnect(&socket->xref);
- goto connection_closed;
- }
+ peer = xref_get_peer_and_lock(&socket->xref);
+ if (!peer)
+ goto no_peer;
appctx = container_of(peer, struct appctx, ctx.hlua_cosocket.xref);
si = appctx->owner;
s = si_strm(si);
/* Return result. */
luaL_pushresult(&socket->b);
+ xref_unlock(&socket->xref, peer);
return 1;
connection_closed:
+ xref_unlock(&socket->xref, peer);
+
+no_peer:
+
/* If the buffer containds data. */
if (socket->b.n > 0) {
luaL_pushresult(&socket->b);
connection_empty:
appctx = objt_appctx(s->si[0].end);
- if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_read, hlua->task))
+ if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_read, hlua->task)) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "out of memory"));
+ }
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_receive_yield, TICK_ETERNITY, 0));
return 0;
}
WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
/* check for connection break. If some data where read, return it. */
- peer = xref_get_peer(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
if (!peer) {
- xref_disconnect(&socket->xref);
lua_pushinteger(L, -1);
return 1;
}
/* Check for connection close. */
if (channel_output_closed(&s->req)) {
+ xref_unlock(&socket->xref, peer);
lua_pushinteger(L, -1);
return 1;
}
send_len = buf_len - sent;
/* All the data are sent. */
- if (sent >= buf_len)
+ if (sent >= buf_len) {
+ xref_unlock(&socket->xref, peer);
return 1; /* Implicitly return the length sent. */
+ }
/* Check if the buffer is avalaible because HAProxy doesn't allocate
* the request buffer if its not required.
len = buffer_total_space(s->req.buf);
if (len <= 0) {
appctx = objt_appctx(s->si[0].end);
- if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
+ if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "out of memory"));
+ }
goto hlua_socket_write_yield_return;
}
MAY_LJMP(hlua_socket_close(L));
lua_pop(L, 1);
lua_pushinteger(L, -1);
+ xref_unlock(&socket->xref, peer);
return 1;
}
lua_pushinteger(L, sent + len);
/* All the data buffer is sent ? */
- if (sent + len >= buf_len)
+ if (sent + len >= buf_len) {
+ xref_unlock(&socket->xref, peer);
return 1;
+ }
hlua_socket_write_yield_return:
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_write_yield, TICK_ETERNITY, 0));
return 0;
}
struct appctx *appctx;
struct stream_interface *si;
struct stream *s;
+ int ret;
MAY_LJMP(check_args(L, 1, "getpeername"));
WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
/* check for connection break. If some data where read, return it. */
- peer = xref_get_peer(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
if (!peer) {
- xref_disconnect(&socket->xref);
lua_pushnil(L);
return 1;
}
conn = objt_conn(s->si[1].end);
if (!conn) {
+ xref_unlock(&socket->xref, peer);
lua_pushnil(L);
return 1;
}
conn_get_to_addr(conn);
if (!(conn->flags & CO_FL_ADDR_TO_SET)) {
+ xref_unlock(&socket->xref, peer);
lua_pushnil(L);
return 1;
}
- return MAY_LJMP(hlua_socket_info(L, &conn->addr.to));
+ ret = MAY_LJMP(hlua_socket_info(L, &conn->addr.to));
+ xref_unlock(&socket->xref, peer);
+ return ret;
}
/* Returns information about my connection side. */
struct xref *peer;
struct stream_interface *si;
struct stream *s;
+ int ret;
MAY_LJMP(check_args(L, 1, "getsockname"));
WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
/* check for connection break. If some data where read, return it. */
- peer = xref_get_peer(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
if (!peer) {
- xref_disconnect(&socket->xref);
lua_pushnil(L);
return 1;
}
conn = objt_conn(s->si[1].end);
if (!conn) {
+ xref_unlock(&socket->xref, peer);
lua_pushnil(L);
return 1;
}
conn_get_from_addr(conn);
if (!(conn->flags & CO_FL_ADDR_FROM_SET)) {
+ xref_unlock(&socket->xref, peer);
lua_pushnil(L);
return 1;
}
- return hlua_socket_info(L, &conn->addr.from);
+ ret = hlua_socket_info(L, &conn->addr.from);
+ xref_unlock(&socket->xref, peer);
+ return ret;
}
/* This struct define the applet. */
WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
/* check for connection break. If some data where read, return it. */
- peer = xref_get_peer(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
if (!peer) {
- xref_disconnect(&socket->xref);
lua_pushnil(L);
lua_pushstring(L, "Can't connect");
return 2;
/* Check if we run on the same thread than the xreator thread.
* We cannot access to the socket if the thread is different.
*/
- if (socket->tid != tid)
+ if (socket->tid != tid) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
+ }
/* Check for connection close. */
if (!hlua || channel_output_closed(&s->req)) {
+ xref_unlock(&socket->xref, peer);
lua_pushnil(L);
lua_pushstring(L, "Can't connect");
return 2;
/* Check for connection established. */
if (appctx->ctx.hlua_cosocket.connected) {
+ xref_unlock(&socket->xref, peer);
lua_pushinteger(L, 1);
return 1;
}
- if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
+ if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "out of memory error"));
+ }
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
return 0;
}
port = MAY_LJMP(luaL_checkinteger(L, 3));
/* check for connection break. If some data where read, return it. */
- peer = xref_get_peer(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
if (!peer) {
- xref_disconnect(&socket->xref);
lua_pushnil(L);
return 1;
}
/* Initialise connection. */
conn = si_alloc_conn(&s->si[1]);
- if (!conn)
+ if (!conn) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "connect: internal error"));
+ }
/* needed for the connection not to be closed */
conn->target = s->target;
/* Parse ip address. */
addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, 0);
- if (!addr)
+ if (!addr) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "connect: cannot parse destination address '%s'", ip));
- if (low != high)
+ }
+ if (low != high) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "connect: port ranges not supported : address '%s'", ip));
+ }
memcpy(&conn->addr.to, addr, sizeof(struct sockaddr_storage));
/* Set port. */
if (low == 0) {
if (conn->addr.to.ss_family == AF_INET) {
- if (port == -1)
+ if (port == -1) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "connect: port missing"));
+ }
((struct sockaddr_in *)&conn->addr.to)->sin_port = htons(port);
} else if (conn->addr.to.ss_family == AF_INET6) {
- if (port == -1)
+ if (port == -1) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "connect: port missing"));
+ }
((struct sockaddr_in6 *)&conn->addr.to)->sin6_port = htons(port);
}
}
hlua->flags |= HLUA_MUST_GC;
- if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task))
+ if (!notification_new(&hlua->com, &appctx->ctx.hlua_cosocket.wake_on_write, hlua->task)) {
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "out of memory"));
+ }
+ xref_unlock(&socket->xref, peer);
WILL_LJMP(hlua_yieldk(L, 0, 0, hlua_socket_connect_yield, TICK_ETERNITY, 0));
return 0;
socket = MAY_LJMP(hlua_checksocket(L, 1));
/* check for connection break. If some data where read, return it. */
- peer = xref_get_peer(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
if (!peer) {
- xref_disconnect(&socket->xref);
lua_pushnil(L);
return 1;
}
s = si_strm(si);
s->target = &socket_ssl.obj_type;
+ xref_unlock(&socket->xref, peer);
return MAY_LJMP(hlua_socket_connect(L));
}
#endif
WILL_LJMP(luaL_error(L, "connect: cannot use socket on other thread"));
/* check for connection break. If some data where read, return it. */
- peer = xref_get_peer(&socket->xref);
+ peer = xref_get_peer_and_lock(&socket->xref);
if (!peer) {
- xref_disconnect(&socket->xref);
hlua_pusherror(L, "socket: not yet initialised, you can't set timeouts.");
WILL_LJMP(lua_error(L));
return 0;
s->req.wto = tmout;
s->res.rto = tmout;
s->res.wto = tmout;
+ xref_unlock(&socket->xref, peer);
return 0;
}