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;
}

Reply via email to