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.
I'm using fread(3)
and fwrite(3)
. I have heard of select(2)
, 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 fopencookie(3)
, useful for tests and other things, too. I have tried setting up SIGALRM
with alarm(2)
to get the EINTR
error from fread(3)
(setting up a callback for SIGALRM
using signal(2)
), but it won't stop the fopen
call as expected...
Thanks in advance for any solution.
EDIT: So it looks like this works.. but only once. On the second call, it doesn't... Oo
/**
* 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, &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);
}
Again, thanks for any help ^^