title: FILE* reading with timeout
body: <p>I'm making a communication library that takes a filestream and uses it to read and write. The protocol defines timeouts, so I want to use them.</p>
  
  <p>I'm using <code>fread(3)</code> and <code>fwrite(3)</code>. I have heard of <code>select(2)</code>, and it's what I'm looking for, except it uses file descriptors and not libc filestreams - I want to support custom filestreams created with <code>fopencookie(3)</code>, useful for tests and other things, too. I have tried setting up <code>SIGALRM</code> with <code>alarm(2)</code> to get the <code>EINTR</code> error from <code>fread(3)</code> (setting up a callback for <code>SIGALRM</code> using <code>signal(2)</code>), but it won't stop the <code>fopen</code> call as expected...</p>
  
  <p>Thanks in advance for any solution.</p>
  
  <p><strong>EDIT</strong>: So it looks like this works.. but only once. On the second call, it doesn't... Oo</p>
  
  <pre><code>/**
   *  sigalrm_handler:
   *  Shut up SIGALRM.
   *
   *  @arg    code        signal code (always SIGALRM)
   */
  
  static __thread jmp_buf env_alrm;
  static void sigalrm_handler(int signo)
  {
      (void)signo;
      /* restore env */
      longjmp(env_alrm, 5);
  }
  
  /**
   *  _p7_fread:
   *  Read file with timeout.
   *
   *  @arg    ptr         the buffer pointer
   *  @arg    size        the size of an item
   *  @arg    nitems      the number of items in the buffer
   *  @arg    stream      the stream
   *  @arg    timeout     the timeout (seconds)
   *  @return             the number of read bytes
   */
  
  size_t _p7_fread(void *ptr, size_t size, size_t nitems, FILE *stream,
      int timeout)
  {
      size_t read_count = 0;
  
      /* set long jump */
      int val = setjmp(env_alrm);
      if (!val) {
      /* setup signal handler */
          if (signal(SIGALRM, &amp;sigalrm_handler) == SIG_ERR)
              return (0);
  
          /* setup alarm */
          alarm(timeout);
  
          /* read */
          read_count = fread(ptr, size, nitems, stream);
      } else
          errno = EINTR;
  
      /* unset signal handler and alarm */
      signal(SIGALRM, NULL);
      alarm(0);
  
      /* return */
      return (read_count);
  }
  </code></pre>
  
  <p>Again, thanks for any help ^^</p>