getrandom.2: treatment of interrupts

From: Heinrich Schuchardt
Date: Sat Nov 22 2014 - 06:36:44 EST


Hello Theodore,

I created the test program below.

While running it I issued
kill -SIGUSR1 <pid>
and
kill -SIGUSR2 <pid>

What I found was rather strange.

No matter whether specifying GRND_NONBLOCK or not, signals do not interrupt the execution of getrandom() while reading from the /dev/urandom pool.

Only after getrandom has finished signals are handled.

I would have expected getrandom() to react to interrupts immediately and to return whatever number of random bytes have been collected before the interrupt.

A system call not reacting to interrupts for several seconds looks like a bug to me.

Tested on Linux 3.18.0-rc4 mips64.

Best regards

Heinrich Schuchardt



#define _GNU_SOURCE
#include <errno.h>
#include <linux/unistd.h>
#include <linux/random.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>

#if _MIPS_SIM == _MIPS_SIM_ABI32
#define __NR_getrandom (__NR_Linux + 353)
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */

#if _MIPS_SIM == _MIPS_SIM_ABI64
#define __NR_getrandom (__NR_Linux + 313)
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */

#if _MIPS_SIM == _MIPS_SIM_NABI32
#define __NR_getrandom (__NR_Linux + 317)
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */

#ifdef __i386__
#define __NR_getrandom (355)
#endif /* __i386__ */

#ifdef __x86_64__
#define __NR_getrandom (318)
#endif /* __x86_64__ */

#define SYS_getrandom __NR_getrandom

#define GRND_NONBLOCK 0x0001
#define GRND_RANDOM 0x0002

#define BUFLEN 0x12345678

int getrandom(void *buf, size_t buflen, unsigned int flags)
{
return syscall(SYS_getrandom, buf, buflen, flags);
}

/**
* Handles signal.
*
* @param sig signal
*/


int do_print = 0;

static void hdl(int sig)
{
if (sig == SIGUSR1) {
fprintf(stderr, "Main received SIGUSR1\n");
do_print = 1;
}
}

int
main(int argc, char *argv[])
{

char *buf;
size_t buflen = BUFLEN;
int ret;
pid_t pid;
// action to take when signal occurs
struct sigaction act;
// signal mask
sigset_t blockset;


pid = getpid();

printf("PID = %u\n", pid);

printf("__NR_getrandom = %u\n", __NR_getrandom);

// Set handler for SIGUSR1
act.sa_handler = hdl;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(SIGUSR1, &act, NULL)) {
perror("sigaction");
exit(EXIT_FAILURE);
}

buf = (char *) malloc(buflen);
if (buf == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}

buf = (char *) malloc(buflen);

for (;;) {
ret = getrandom(buf, buflen, GRND_NONBLOCK);
if (ret == -1) {
fprintf(stderr, "errno = %d\n", errno);
perror("getrandom");
exit(EXIT_FAILURE);
}
if (do_print) {
do_print = 0;
printf("ret = %d\n", ret);
}

}
printf("ret = %d\n", ret);

free(buf);

return EXIT_SUCCESS;
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/