From 1d483eea84bbb9463a64384817690109fdf81942 Mon Sep 17 00:00:00 2001 From: compudj Date: Mon, 13 Jun 2005 16:43:36 +0000 Subject: [PATCH] daemon works git-svn-id: http://ltt.polymtl.ca/svn@947 04897980-b3bd-0310-b5e0-8ef037075253 --- ltt/branches/poly/lttd/lttd.c | 165 ++++++++++++++++++++++++++++++++-- 1 file changed, 159 insertions(+), 6 deletions(-) diff --git a/ltt/branches/poly/lttd/lttd.c b/ltt/branches/poly/lttd/lttd.c index 04c2ec1..e090729 100644 --- a/ltt/branches/poly/lttd/lttd.c +++ b/ltt/branches/poly/lttd/lttd.c @@ -10,16 +10,34 @@ * Mathieu Desnoyers */ +#define _GNU_SOURCE #include +#include #include #include #include -#include #include #include #include #include #include +#include +#include + +/* Relayfs IOCTL */ +#include +#include + +/* Get the next sub buffer that can be read. */ +#define RELAYFS_GET_SUBBUF _IOR(0xF4, 0x00,__u32) +/* Release the oldest reserved (by "get") sub buffer. */ +#define RELAYFS_PUT_SUBBUF _IO(0xF4, 0x01) +/* returns the number of sub buffers in the per cpu channel. */ +#define RELAYFS_GET_N_SUBBUFS _IOR(0xF4, 0x02,__u32) +/* returns the size of the sub buffers. */ +#define RELAYFS_GET_SUBBUF_SIZE _IOR(0xF4, 0x03,__u32) + + enum { GET_SUBBUF, @@ -31,6 +49,9 @@ enum { struct fd_pair { int channel; int trace; + unsigned int n_subbufs; + unsigned int subbuf_size; + void *mmap; }; struct channel_trace_fd { @@ -42,6 +63,7 @@ static char *trace_name = NULL; static char *channel_name = NULL; static int daemon_mode = 0; static int append_mode = 0; +volatile static int quit_program = 0; /* For signal handler */ /* Args : * @@ -143,6 +165,16 @@ void show_info(void) } +/* signal handling */ + +static void handler(int signo) +{ + printf("Signal %d received : exiting cleanly\n", signo); + quit_program = 1; +} + + + int open_channel_trace_pairs(char *subchannel_name, char *subtrace_name, struct channel_trace_fd *fd_pairs) { @@ -254,6 +286,42 @@ int open_channel_trace_pairs(char *subchannel_name, char *subtrace_name, return 0; } + +int read_subbuffer(struct fd_pair *pair) +{ + unsigned int subbuf_index; + int ret; + + + ret = ioctl(pair->channel, RELAYFS_GET_SUBBUF, + &subbuf_index); + if(ret != 0) { + perror("Error in reserving sub buffer"); + goto error; + } + + ret = TEMP_FAILURE_RETRY(write(pair->trace, + pair->mmap + (subbuf_index * pair->subbuf_size), + pair->subbuf_size)); + + if(ret != 0) { + perror("Error in writing to file"); + goto error; + } + + + ret = ioctl(pair->channel, RELAYFS_PUT_SUBBUF); + if(ret != 0) { + perror("Error in unreserving sub buffer"); + goto error; + } + + return 0; +error: + return -1; +} + + /* read_channels * * Read the realyfs channels and write them in the paired tracefiles. @@ -273,12 +341,48 @@ int open_channel_trace_pairs(char *subchannel_name, char *subtrace_name, int read_channels(struct channel_trace_fd *fd_pairs) { struct pollfd *pollfd; - int i; - int num_rdy; + int i,j; + int num_rdy, num_hup; int high_prio; + int ret; + + /* Get the subbuf sizes and number */ + + for(i=0;inum_pairs;i++) { + struct fd_pair *pair = &fd_pairs->pair[i]; + ret = ioctl(pair->channel, RELAYFS_GET_N_SUBBUFS, + &pair->n_subbufs); + if(ret != 0) { + perror("Error in getting the number of subbuffers"); + goto end; + } + ret = ioctl(pair->channel, RELAYFS_GET_SUBBUF_SIZE, + &pair->subbuf_size); + if(ret != 0) { + perror("Error in getting the size of the subbuffers"); + goto end; + } + } + + /* Mmap each FD */ + for(i=0;inum_pairs;i++) { + struct fd_pair *pair = &fd_pairs->pair[i]; + + pair->mmap = mmap(0, pair->subbuf_size * pair->n_subbufs, PROT_READ, + MAP_SHARED, pair->channel, 0); + if(pair->mmap == MAP_FAILED) { + perror("Mmap error"); + goto munmap; + } + } + + + /* Start polling the FD */ + pollfd = malloc(fd_pairs->num_pairs * sizeof(struct pollfd)); + /* Note : index in pollfd is the same index as fd_pair->pair */ for(i=0;inum_pairs;i++) { pollfd[i].fd = fd_pairs->pair[i].channel; pollfd[i].events = POLLIN|POLLPRI; @@ -286,11 +390,21 @@ int read_channels(struct channel_trace_fd *fd_pairs) while(1) { high_prio = 0; - + num_hup = 0; +#ifdef DEBUG + printf("Press a key for next poll...\n"); + char buf[1]; + read(STDIN_FILENO, &buf, 1); + printf("Next poll :\n"); +#endif //DEBUG + + /* Have we received a signal ? */ + if(quit_program) break; + num_rdy = poll(pollfd, fd_pairs->num_pairs, -1); if(num_rdy == -1) { perror("Poll error"); - return -1; + goto free_fd; } printf("Data received\n"); @@ -299,25 +413,34 @@ int read_channels(struct channel_trace_fd *fd_pairs) switch(pollfd[i].revents) { case POLLERR: printf("Error returned in polling fd %d.\n", pollfd[i].fd); + num_hup++; break; case POLLHUP: printf("Polling fd %d tells it has hung up.\n", pollfd[i].fd); + num_hup++; break; case POLLNVAL: printf("Polling fd %d tells fd is not open.\n", pollfd[i].fd); + num_hup++; break; case POLLPRI: + printf("Urgent read on fd %d\n", pollfd[i].fd); /* Take care of high priority channels first. */ high_prio = 1; + ret |= read_subbuffer(&fd_pairs->pair[i]); break; } } + /* If every FD has hung up, we end the read loop here */ + if(num_hup == fd_pairs->num_pairs) break; if(!high_prio) { for(i=0;inum_pairs;i++) { switch(pollfd[i].revents) { case POLLIN: /* Take care of low priority channels. */ + printf("Normal read on fd %d\n", pollfd[i].fd); + ret |= read_subbuffer(&fd_pairs->pair[i]); break; } } @@ -325,9 +448,26 @@ int read_channels(struct channel_trace_fd *fd_pairs) } +free_fd: free(pollfd); - return 0; + /* munmap only the successfully mmapped indexes */ + i = fd_pairs->num_pairs; +munmap: + /* Munmap each FD */ + for(j=0;jpair[j]; + int err_ret; + + err_ret = munmap(pair->mmap, pair->subbuf_size * pair->n_subbufs); + if(err_ret != 0) { + perror("Error in munmap"); + } + ret |= err_ret; + } + +end: + return ret; } @@ -350,6 +490,7 @@ int main(int argc, char ** argv) int ret; pid_t pid; struct channel_trace_fd fd_pairs = { NULL, 0 }; + struct sigaction act; ret = parse_arguments(argc, argv); @@ -373,6 +514,18 @@ int main(int argc, char ** argv) /* else, we are the child, continue... */ } + /* Connect the signal handlers */ + act.sa_handler = handler; + act.sa_flags = 0; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGTERM); + sigaddset(&(act.sa_mask), SIGQUIT); + sigaddset(&(act.sa_mask), SIGINT); + sigaction(SIGTERM, &act, NULL); + sigaction(SIGQUIT, &act, NULL); + sigaction(SIGINT, &act, NULL); + + //return 0; if(ret = open_channel_trace_pairs(channel_name, trace_name, &fd_pairs)) goto close_channel; -- 2.34.1