Hi Kevin,

On 09/17/2014 11:27 AM, Kevin Hendricks wrote:
> Hello Everyone,
> 
> I only have a few days experience with libuv, but done a lot of reading
> of uv.h, the libuv-dox, and other resources, and I've gotten both a udp
> client and udp echo server running with just libuv. I understand all the
> memory management is on the user, which is an area I'm pretty green in.
> I'm using the current version of the master branch.
> 

FYI, we have better docs now! http://docs.libuv.org
Also, I suggest to switch to using the v1.x branch.

> Both programs are fairly simple: the client opens a socket for sending
> and recieving, and while loops calls to uv_udp_send hundreds of char *
> packets ("packet 1," "packet 2," etc.), individually malloc'd, to the
> server. The server opens a socket for receiving, has a receive callback
> that prints the message, copies that into a newly allocated buffer,
> sends it back to the same addr it got it from, and frees() the received
> buf->base. The client receives the echoed message, prints it, and frees
> the received buffer. So far that's the strategy I've seen in all the
> examples.
> 

That sounds ok.

> In both cases, that leaves the send buffers to be freed. I realized I
> couldn't free them immediately after calling uv_udp_send, since that
> just points to the buffer and doesn't send it right away. So I went to
> free it in the send callback, but unlike the receive and read cbs, you
> can't just free(buf->base). I tried free(req->bufs[0].base) similar to
> the write examples, but it appears to have already been freed and set to
> null in uv__udp_run_completed, before the callback is called. So that
> segfaults, but free(req->bufsml[0].base) works and gives no valgrind
> errors or leaks. I tried iterating over all non-null array entries in
> bufsml [ int i=0; while (req->bufsml[i].base) free(req->bufsml[i].base);
> ++i;  ] but that gives me one valgrind error per packet ("Conditional
> jump or move depends on uninitialised value(s)").
> 
> Am I doing this right?
> 

Nope. libuv will copy the buffer structures you pass to uv_udp_send, but
not the content. That is left up to you to free.

> I haven't been able to find any samples or examples of udp echo servers
> using libuv that even free memory in the send_cb other than free(req),
> but as far as I can tell, they all have memory leaks. The tcp server
> example in libuv-dox uses free(wr->buf.base) in its write_cb, but
> valgrind reports it has a huge memory leak (maybe it didn't 8 or 9
> months ago with the version it was made for, but it does now). I don't
> know what the difference between bufs and bufsml is, and don't know if I
> should be concerned that I can't seem to check all members of the bufsml
> array to see if I should free them, only blindly free the first. It
> seems like this is harder than it should be.
> 

The way to solve this elegantly is to embed the uv_udp_send_t structure
into another one:

typedef struct {
   uv_udp_send_t req;
   char *data;
} udp_send_ctx_t;

Then malloc one of these and pass &ctx->req to uv_udp_send. In the
callback, you can do the following to get a pointer to your context:

udp_send_ctx_t* ctx = container_of(req, udp_send_ctx_t, req);

And then you can just free ctx->data.


Cheers,

-- 
Saúl Ibarra Corretgé
bettercallsaghul.com


Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to