Hi guys,

I'm doing some tests with broadcasting a message to several http
clients, implemented with libevent. I'm currently with a segfault,
that is demonstrated by the attached source code, that happens when
you broadcast several messages to the connected clients.

The steps to reproduce the segfault are:
1. compile the attached code: gcc test1.c -o test1 -Wall -levent
2. run it
3. access by a browser the URL: http://127.0.0.1:8000/test/1
4. press enter on the terminal running test1
5. at least here, i get a segfault :)

I'm using libevent-1.4.9-stable, compiled by myself with debug enabled.

Am I doing something wrong? Is this a bug?

Thanks in advance.
#include <sys/types.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <stdlib.h>
#include <err.h>
#include <event.h>
#include <evhttp.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <pthread.h>

#define BUFSIZE 1024
#define MAXUSERS (17*65536)	// C1024K

struct evhttp_request *clients[MAXUSERS];
int slots[MAXUSERS];

void
cleanup (struct evhttp_connection *evcon, void *arg) {
  int *uidp = (int *) arg;
  fprintf (stderr, "disconnected uid %d\n", *uidp + 1);
  clients[*uidp - 1] = NULL;
}

void
request_handler (struct evhttp_request *req, void *arg) {
  struct evbuffer *buf;
  buf = evbuffer_new ();

  if (buf == NULL) {
    err (1, "failed to create response buffer");
  }

  evhttp_add_header (req->output_headers, "Content-Type", "text/html; charset=utf-8");

  int uid = -1;
  if (strncmp (evhttp_request_uri (req), "/test/", 6) == 0) {
    uid = atoi (6 + evhttp_request_uri (req));
  }

  if (uid <= 0) {
    evbuffer_add_printf (buf, "User id not found, try /test/123 instead");
    evhttp_send_reply (req, HTTP_NOTFOUND, "Not Found", buf);
    evbuffer_free (buf);
    return;
  }

  if (uid > MAXUSERS) {
    evbuffer_add_printf (buf, "Max uid allowed is %d", MAXUSERS);
    evhttp_send_reply (req, HTTP_SERVUNAVAIL, "We ran out of numbers", buf);
    evbuffer_free (buf);
    return;
  }

  evhttp_send_reply_start (req, HTTP_OK, "OK");
  evbuffer_add_printf (buf, "Welcome, Url: ‘%s’ Id: %d\n", evhttp_request_uri (req), uid);
  evhttp_send_reply_chunk (req, buf);
  evbuffer_free (buf);

  clients[uid - 1] = req;
  evhttp_connection_set_closecb (req->evcon, cleanup, &slots[uid - 1]);
}


void
run () {
  struct evbuffer *evbuf;

  while (1) {
    char body[4096];
    int body_len, clientId;
    time_t start = time (NULL);
    int i;

    printf ("Please press enter: ");
    fgets (body, sizeof (body), stdin);

    for (i = 0; i < 1000; i++) {
      sprintf (body, "Hello world #%d<br>", i + 1);
      body_len = strlen (body);

      printf ("Sending %d bytes to the clients: %s\n", body_len, body);

      for (clientId = 0; clientId < MAXUSERS && clients[clientId] != NULL; clientId++) {
	    evbuf = evbuffer_new ();
	    evbuffer_add_printf (evbuf, "(%ld) %s<br>", time (NULL) - start, body);

	    printf ("Sending to client %d\n", clientId + 1);

	    evhttp_send_reply_chunk (clients[clientId], evbuf);
	    evbuffer_free (evbuf);
      }

    }

  }
  pthread_exit (0);
}

int
main (int argc, char **argv) {
  pthread_t helper;
  pthread_create (&helper, NULL, run, NULL);

  int i;
  for (i = 0; i < MAXUSERS; i++)
    slots[i] = i;
  // Launch libevent httpd:
  struct evhttp *httpd;
  event_init ();
  httpd = evhttp_start ("0.0.0.0", 8000);
  evhttp_set_gencb (httpd, request_handler, NULL);
  event_dispatch ();
  // Not reached, event_dispatch() shouldn’t return
  evhttp_free (httpd);
  return 0;
}
_______________________________________________
Libevent-users mailing list
Libevent-users@monkey.org
http://monkeymail.org/mailman/listinfo/libevent-users

Reply via email to