It's not a race (no threads=> no races!), I had forgotten to initialize
the size of the response. I've added a global flag for "terminate after
one round" as well now.
-Christian
On 10/29/2011 04:16 PM, Sven Geggus wrote:
Christian Grothoff schrieb am Samstag, den 29. Oktober um 15:28 Uhr:
I've attached a completed example that writes every 4s a "Round %d"
string to the client (based on the trigger). I've added comments
where appropriate.
Thank you very much!
There seems to be a race condition somewhere:
While testing my "wget -O - -q http://localhost:8888/" call sometimes just
returns
an empty document:
HTTP/1.0 200 OK..Content-Length: 0..Date: Sat, 29 Oct 2011 14:12:32 GMT....
Besides what would I need to modify in the code to close the client
socket right after one round has been sent to the client?
Regards
Sven
#include <stdio.h>
#include <stdlib.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <string.h>
#include <microhttpd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#define PAGE "<html><head><title>File not found</title></head><body>File not found</body></html>"
static int acgen;
static int terminate_after_one_round;
static ssize_t file_reader (void *cls, uint64_t pos, char *buf, size_t max) {
int * gp = cls;
ssize_t ret;
if (*gp == -1)
return MHD_CONTENT_READER_END_OF_STREAM;
if (*gp == acgen)
return 0; /* no data */
ret = 0;
while ( (max > ret + 20) && ((*gp) < acgen) )
{
ret += snprintf (&buf[ret], max - ret, "Round %d\n", acgen);
(*gp)++; /* remember how many rounds we did transmit to this client so far */
if (terminate_after_one_round)
{
*gp = -1; /* set termination flag */
}
}
return ret;
}
static void free_callback (void *cls) {
fprintf (stderr, "freeing reader\n");
free (cls);
}
static int ahc_echo (void *cls,
struct MHD_Connection *connection,
const char *url,
const char *method,
const char *version,
const char *upload_data,
size_t *upload_data_size, void **ptr) {
static int aptr;
struct MHD_Response *response;
int ret;
int *gp;
if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
return MHD_NO; /* unexpected method */
if (&aptr != *ptr)
{
/* do never respond on first call */
*ptr = &aptr;
return MHD_YES;
}
*ptr = NULL; /* reset when done */
gp = malloc (sizeof (int));
*gp = acgen; /* current generation -- to only send rounds from connect on */
if (NULL == gp)
return MHD_NO;
fprintf (stderr, "creating reader\n");
response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
32 * 1024, /* 32k page size */
&file_reader,
gp,
&free_callback);
if (response == NULL)
{
free (gp);
return MHD_NO;
}
ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
MHD_destroy_response (response);
return ret;
}
int main () {
struct MHD_Daemon *d;
fd_set rs;
fd_set ws;
fd_set es;
int max,rtcfd;
unsigned long data;
int tirq,acqdelay=4;
d = MHD_start_daemon (MHD_USE_DEBUG,
8888,
NULL, NULL, &ahc_echo, PAGE, MHD_OPTION_END);
if (d == NULL)
return 1;
rtcfd = open("/dev/rtc0", O_RDONLY);
if (rtcfd == -1) {
fprintf(stderr,"error opening /dev/rtc0");
exit(EXIT_FAILURE);
}
/* Turn on update interrupts (one per second) */
ioctl(rtcfd, RTC_UIE_ON, 0);
tirq=acqdelay-1;
while (1) {
max = 0;
FD_ZERO (&rs);
FD_ZERO (&ws);
FD_ZERO (&es);
if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
break; /* fatal internal error */
FD_SET(rtcfd,&rs);
if (rtcfd >max) max=rtcfd;
select (max + 1, &rs, &ws, &es, NULL);
if (FD_ISSET(rtcfd,&rs)) {
read(rtcfd, &data, sizeof(unsigned long));
tirq++;
if (tirq==acqdelay) {
acgen++; /* count up generation to trigger transmission */
printf("do data acq here\n");
tirq=0;
}
}
/* NOTE: *always* run MHD_run() in external select loop! */
MHD_run (d);
}
MHD_stop_daemon (d);
return 0;
}