void * growing_fifo_write(struct fifo_buffer **buffer_p, size_t length) { assert(buffer_p != NULL); struct fifo_buffer *buffer = *buffer_p; assert(buffer != NULL); size_t max_length; void *p = fifo_buffer_write(buffer, &max_length); if (p != NULL && max_length >= length) return p; /* grow */ size_t new_size = fifo_buffer_available(buffer) + length; assert(new_size > fifo_buffer_capacity(buffer)); *buffer_p = buffer = fifo_buffer_realloc(buffer, align(new_size)); /* try again */ p = fifo_buffer_write(buffer, &max_length); assert(p != NULL); assert(max_length >= length); return p; }
/* the single writer thread */ void *worker_thread(void *arg) { int frame_size; int fifo_fd = -1; struct timeval timestamp; while(fifo_fd == -1) { fifo_fd = open(fifoname, O_RDONLY); if (fifo_fd < 0) { fprintf(stderr, "reopen(%s) failed: %d\n", fifoname, errno); sleep(10); } } /* set cleanup handler to cleanup allocated ressources */ pthread_cleanup_push(worker_cleanup, NULL); fifo_buffer = (char*)malloc(fifo_buffer_size); size_t fifo_buffer_used = 0; char *head; char* frame_delim1; pglobal->in[plugin_number].buf = malloc(fifo_buffer_size); while(!pglobal->stop) { frame_delim1 = NULL; int read_res = read(fifo_fd, fifo_buffer + fifo_buffer_used, fifo_buffer_available()); if (read_res <= 0) { if (read_res == 0) fprintf(stderr, "read(%d, %zu) eof\n", fifo_fd, fifo_buffer_available()); else { fprintf(stderr, "read(%d, %zu) failed: %d\n", fifo_fd, fifo_buffer_available(), errno); perror("read failed"); } if (fifo_fd != -1 && close(fifo_fd) != 0) { int res = errno; fprintf(stderr, "close(%s) failed: %d\n", fifoname, res); return NULL; } fifo_fd = -1; while(fifo_fd == -1) { fifo_fd = open(fifoname, O_RDONLY); if (fifo_fd < 0) { int res = errno; fprintf(stderr, "reopen(%s) failed: %d\n", fifoname, res); } sleep(10); } fifo_buffer_used = 0; fprintf(stderr,"reopened %d %d\n",fifo_fd, read_res); continue; } fifo_buffer_used += read_res; head = fifo_buffer; int frame_cnt = 0; while(NULL != (frame_delim1 = (char*)memmem(head, fifo_buffer_used - (head - fifo_buffer), frame_delim, frame_delim_size))) { frame_size = frame_delim1 - head; if(frame_size != 0) { /* copy frame from file to global buffer */ pthread_mutex_lock(&pglobal->in[plugin_number].db); pglobal->in[plugin_number].size = frame_size; memcpy(pglobal->in[plugin_number].buf, head, frame_size); frame_cnt++; gettimeofday(×tamp, NULL); pglobal->in[plugin_number].timestamp = timestamp; DBG("new frame copied (size: %d)\n", pglobal->in[plugin_number].size); /* signal fresh_frame */ pthread_cond_broadcast(&pglobal->in[plugin_number].db_update); pthread_mutex_unlock(&pglobal->in[plugin_number].db); } else { perror("empty frame"); } head = frame_delim1 + frame_delim_size; if(delay != 0) usleep(1000 * delay); } fifo_buffer_used -= (head - fifo_buffer); memmove(fifo_buffer, head, fifo_buffer_used); } //thread_quit: free(pglobal->in[plugin_number].buf); DBG("leaving input thread, calling cleanup function now\n"); /* call cleanup handler, signal with the parameter */ pthread_cleanup_pop(1); return NULL; }