I just noticed that I can cause a SEGFAULT inside libuv 1.8.0 (from Ubuntu
repos) if I try to stop reading from a 'uv_udp_t' or 'uv_tcp_t' in the
'uv_alloc_cb' callback by invoking 'uv_udp_recv_stop' or 'uv_read_stop'
(see attached files 'segfault_udp.c' and 'segfault_tcp.c'). If this is
intentional, could the manual tell we should avoid such usage either in
'uv_alloc_cb' or 'uv_udp_recv_stop' and 'uv_read_stop' descriptions?
To avoid this SEGFAULT, I'll delay the call to 'uv_udp_recv_stop' or
'uv_read_stop' until the correspondig 'uv_udp_recv_cb' or 'uv_read_cb' is
called (see attached files 'workaround_udp.c' and 'workaround_tcp.c'). Can
I use the fact that filling the 'uv_buf_t' structure with '.base = NULL'
and '.len = 0' will cause a 'UV_ENOBUFS' error or this error code may be
raised by system dependent circustances as well?
--
Renato Maia.
--
You received this message because you are subscribed to the Google Groups
"libuv" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/libuv.
For more options, visit https://groups.google.com/d/optout.
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <uv.h>
static void onread (uv_stream_t *stream, ssize_t nread, const uv_buf_t *buffer)
{
assert(0);
}
static void onalloc (uv_handle_t *handle, size_t suggested_size, uv_buf_t *buffer)
{
uv_stream_t *stream = (uv_stream_t *)handle;
int err = uv_read_stop(stream);
assert(err >= 0);
}
static void onconnect (uv_connect_t *request, int error)
{
int err = uv_read_start(request->handle, onalloc, onread);
assert(err >= 0);
}
int main(int argc, char const *argv[])
{
uv_loop_t loop;
uv_tcp_t tcp;
uv_connect_t connect;
struct sockaddr_in addr;
int err;
err = uv_loop_init(&loop);
assert(err >= 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
err = uv_inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
assert(err >= 0);
err = uv_tcp_init_ex(&loop, &tcp, AF_INET);
assert(err >= 0);
err = uv_tcp_connect(&connect, &tcp, (const struct sockaddr *)&addr, onconnect);
assert(err >= 0);
err = uv_run(&loop, UV_RUN_DEFAULT);
assert(err >= 0);
return 0;
}
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <uv.h>
static void onread (uv_udp_t* handle,
ssize_t nread,
const uv_buf_t* buf,
const struct sockaddr* addr,
unsigned flags)
{
assert(0);
}
static void onalloc (uv_handle_t *handle, size_t suggested_size, uv_buf_t *buffer)
{
uv_udp_t *stream = (uv_udp_t *)handle;
int err = uv_udp_recv_stop(stream);
assert(err >= 0);
}
int main(int argc, char const *argv[])
{
uv_loop_t loop;
uv_udp_t udp;
struct sockaddr_in addr;
int err;
err = uv_loop_init(&loop);
assert(err >= 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
err = uv_inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
assert(err >= 0);
err = uv_udp_init_ex(&loop, &udp, AF_INET);
assert(err >= 0);
err = uv_udp_bind(&udp, (const struct sockaddr *)&addr, 0);
assert(err >= 0);
err = uv_udp_recv_start(&udp, onalloc, onread);
assert(err >= 0);
err = uv_run(&loop, UV_RUN_DEFAULT);
assert(err >= 0);
return 0;
}
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <uv.h>
static void onread (uv_stream_t *stream, ssize_t nread, const uv_buf_t *buffer)
{
if (nread == UV_ENOBUFS) {
int err = uv_read_stop(stream);
assert(err >= 0);
}
else assert(0);
}
static void onalloc (uv_handle_t *handle, size_t suggested_size, uv_buf_t *buffer)
{
buffer->base = NULL;
buffer->len = 0;
}
static void onconnect (uv_connect_t *request, int error)
{
int err = uv_read_start(request->handle, onalloc, onread);
assert(err >= 0);
}
int main(int argc, char const *argv[])
{
uv_loop_t loop;
uv_tcp_t tcp;
uv_connect_t connect;
struct sockaddr_in addr;
int err;
err = uv_loop_init(&loop);
assert(err >= 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
err = uv_inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
assert(err >= 0);
err = uv_tcp_init_ex(&loop, &tcp, AF_INET);
assert(err >= 0);
err = uv_tcp_connect(&connect, &tcp, (const struct sockaddr *)&addr, onconnect);
assert(err >= 0);
err = uv_run(&loop, UV_RUN_DEFAULT);
assert(err >= 0);
return 0;
}
#include <assert.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <uv.h>
static void onread (uv_udp_t *handle,
ssize_t nread,
const uv_buf_t *buf,
const struct sockaddr *addr,
unsigned flags)
{
if (nread == UV_ENOBUFS) {
int err = uv_udp_recv_stop(handle);
assert(err >= 0);
}
else assert(0);
}
static void onalloc (uv_handle_t *handle, size_t suggested_size, uv_buf_t *buffer)
{
buffer->base = NULL;
buffer->len = 0;
}
int main(int argc, char const *argv[])
{
uv_loop_t loop;
uv_udp_t udp;
struct sockaddr_in addr;
int err;
err = uv_loop_init(&loop);
assert(err >= 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
err = uv_inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
assert(err >= 0);
err = uv_udp_init_ex(&loop, &udp, AF_INET);
assert(err >= 0);
err = uv_udp_bind(&udp, (const struct sockaddr *)&addr, 0);
assert(err >= 0);
err = uv_udp_recv_start(&udp, onalloc, onread);
assert(err >= 0);
err = uv_run(&loop, UV_RUN_DEFAULT);
assert(err >= 0);
return 0;
}