Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to buffer stdout in memory and write it from a dedicated thread

Tags:

I have a C application with many worker threads. It is essential that these do not block so where the worker threads need to write to a file on disk, I have them write to a circular buffer in memory, and then have a dedicated thread for writing that buffer to disk.

The worker threads do not block any more. The dedicated thread can safely block while writing to disk without affecting the worker threads (it does not hold a lock while writing to disk). My memory buffer is tuned to be sufficiently large that the writer thread can keep up.

This all works great. My question is, how do I implement something similar for stdout?

I could macro printf() to write into a memory buffer, but I don't have control over all the code that might write to stdout (some of it is in third-party libraries).

Thoughts? NickB

like image 920
NickB Avatar asked Jun 05 '09 13:06

NickB


1 Answers

I like the idea of using freopen. You might also be able to redirect stdout to a pipe using dup and dup2, and then use read to grab data from the pipe.

Something like so:

#include <stdio.h> #include <stdlib.h> #include <unistd.h>  #define MAX_LEN 40  int main( int argc, char *argv[] ) {   char buffer[MAX_LEN+1] = {0};   int out_pipe[2];   int saved_stdout;    saved_stdout = dup(STDOUT_FILENO);  /* save stdout for display later */    if( pipe(out_pipe) != 0 ) {          /* make a pipe */     exit(1);   }    dup2(out_pipe[1], STDOUT_FILENO);   /* redirect stdout to the pipe */   close(out_pipe[1]);    /* anything sent to printf should now go down the pipe */   printf("ceci n'est pas une pipe");   fflush(stdout);    read(out_pipe[0], buffer, MAX_LEN); /* read from pipe into buffer */    dup2(saved_stdout, STDOUT_FILENO);  /* reconnect stdout for testing */   printf("read: %s\n", buffer);    return 0; } 
like image 74
Nate Kohl Avatar answered Oct 19 '22 10:10

Nate Kohl