On Tue, Nov 7, 2017 at 2:23 AM, Russell Haley <[email protected]> wrote:
> On Monday, November 6, 2017 at 12:14:18 PM UTC-8, Russell Haley wrote:
>> On Monday, November 6, 2017 at 11:49:43 AM UTC-8, Ben Noordhuis wrote:
>>>
>>> On Mon, Nov 6, 2017 at 7:56 PM, Russell Haley <[email protected]> wrote:
>>> > Hello,
>>> >
>>> > I'm new to C patterns and I am experimenting with libuv to write a
>>> > simulator. The idea is to create a context struct to be passed around
>>> > as a
>>> > pointer/handle to various timed and event based callback functions. I
>>> > would
>>> > like this simulator to have a "heartbeat" that sends UDP every x
>>> > period, as
>>> > well as respond to UDP messages received on a different port. I would
>>> > like
>>> > the system to decides at runtime if there are flags in the context that
>>> > block it from sending (i.e. handle->send=0;).
>>> >
>>> > For bonus points, I would like to be able to start a TCP based module
>>> > if I
>>> > receive a certain message on the UDP receive port and then stop it once
>>> > the
>>> > routine completes. I am hoping I can just drop a routine on the default
>>> > loop
>>> > (from within my uv_udp_recv_cb) for processing until completion which
>>> > would
>>> > be signaled in a TCP callback (haven't delved into the TCP stuff
>>> > yet...).
>>> >
>>> > After about 1 hour of searching I haven't found any examples of what I
>>> > am
>>> > trying to do. Most of the example patterns are very simplistic. This
>>> > dearth
>>> > of information leads me to one of two conclusions: 1) I am trying to do
>>> > something the wrong way or 2) nobody in the entirety of using libuv has
>>> > ever
>>> > ever ever tried to do what I am attempting now. I assume the problem is
>>> > the
>>> > former. ;)
>>> >
>>> > What I have so far:
>>> >
>>> > - An example udp listener from the docs. It listens faithfully on the
>>> > port I
>>> > assign.
>>> > - A udp client, again from the docs. My first kick simply sends a
>>> > message
>>> > and then exists . My next planned attempt was to use a timer to send
>>> > the
>>> > information repeatedly. I have realized that the timer callback needs
>>> > to
>>> > have my context handle, which prompted this question. I will finish my
>>> > example code and then post it here while awaiting a possible answer.
>>> >
>>> > Please let me know if I can provide some more background (context? tee
>>> > hee).
>>> >
>>> > Regards,
>>> >
>>> > Russ
>>>
>>> It's not entirely clear to me what you want to accomplish but if you
>>> want to attach state/context to a handle or request, you can use the
>>> handle->data and req->data fields. or embed them in another struct and
>>> use container_of() to look up the embedder.  You can find a
>>> container_of() definition in the libuv sources.
>>
>>
>> Thanks so much for responding. I just stumbled over your answer in uv.h
>> (described in UV_HANDLE_FIELDS) and then found it in the documentation. I
>> missed the context section at the bottom of the basics page.  :(
>>
>> Thanks for the answer and sorry for the noise!
>>
>> Russ
>
>
> Okay, a little more noise. I'm getting a segmentation fault in libuv.so.1
> that I can't seem to debug (unsurprising with my limited gdb skills). The
> following code is my udp client. It's supposed to:
> 1) Set up the context in main()
> 2) Start a timer to tick once, then once per second.
> 3) On each tick, send a udp message and augment the counter.
> 4) If the counter is 10, stop.
>
> udp-spammer.c:
>
> #include <unistd.h>
> #include <stdio.h>
> #include <uv.h>
> #include <stdlib.h>
> #include <string.h>
>
> #define UDP_SEND_PORT           49284
> #define UDP_REC_PORT            49280
>
> #define VMDS_ADDR "127.0.0.1"
> #define TRU_ADDR "127.0.0.1"
> #define ON 1
> #define OFF 0
>
> typedef struct context_t {
>     uv_udp_t* send_ctx;
>     int count;
>     int send;
>     uv_buf_t* message;
> }context_t;
>
>
> static void s_alloc_cb(uv_handle_t* handle, size_t suggested_size, uv_buf_t*
> buf) {
>   buf->base = malloc(suggested_size);
>   buf->len = suggested_size;
> }
>
> void on_send (uv_udp_send_t* req, int status)
> {
>     printf("Status: %d\n",status);
> }
>
> uv_buf_t make_sd_msg(char* msg)
> {
>     uv_buf_t buf = uv_buf_init(msg, strlen(msg));
>     return buf;
> }
>
> void spam(uv_timer_t* h)
> {
>     context_t* ctx = (context_t*)h->data;
>     if(ctx == NULL)
>     {
>         printf("Esplode!");
>         exit(1);
>     }
>
>     struct sockaddr_in broadcast_addr;
>     uv_ip4_addr(VMDS_ADDR, 0, &broadcast_addr);
>     uv_udp_bind(ctx->send_ctx, (const struct sockaddr *)&broadcast_addr, 0);
>
>     uv_udp_send_t send_req;
>
>     struct sockaddr_in remote_addr;
>     uv_ip4_addr(TRU_ADDR, UDP_REC_PORT, &remote_addr);
>     uv_udp_send(&send_req, ctx->send_ctx, ctx->message, 1, (const struct
> sockaddr *)&remote_addr, on_send);
>
>     ctx->count++;
>     if(ctx->count >= 10)
>     {
>         uv_timer_stop(h);
>     }
> }
>
> int main() {
>
>     uv_loop_t *loop;
>     uv_timer_t timed;
>     context_t ctx;
>
>     loop = uv_default_loop();
>
>     ctx.send = 1;
>     ctx.count = 0;
>     uv_buf_t msg =  make_sd_msg("Hello Lucy!\n\0");
>     ctx.message = &msg;
>     uv_udp_t snd;
>     uv_udp_init(loop, &snd);
>     ctx.send_ctx = &snd;
>
>     timed.data = &ctx;
>
>     uv_timer_init(loop, &timed);
>     uv_timer_start(&timed, spam, 0,1000);
>
>     return uv_run(loop, UV_RUN_DEFAULT);
> }
>
>
>
> So far, it sends the first UDP message and then I get a SIGSEV in
> libuv.so.1. bt isn't telling me much that I can use:
>
> 0xb7fad4bd in ?? () from /usr/lib/i386-linux-gnu/libuv.so.1
> (gdb) bt
> #0  0xb7fad4bd in ?? () from /usr/lib/i386-linux-gnu/libuv.so.1
> #1  0xb7fad852 in ?? () from /usr/lib/i386-linux-gnu/libuv.so.1
> #2  0xb7fa0be9 in uv_run () from /usr/lib/i386-linux-gnu/libuv.so.1
> #3  0x08048ad4 in main () at udp-spammer.c:86
>
> Any help would be grand.
>
> Thanks!
> Russ

The `uv_udp_t send_req` in spam() is stack-allocated.  It goes out of
scope and gets clobbered the moment that function returns.  Allocate
it statically or on the heap instead.

Build libuv from source if you want debug symbols, or check if your
distro has a libuv-dbg package or installs debug symbols separately
(e.g, debuginfo-install on Fedora.)

-- 
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.

Reply via email to