getrandom.2: treatment of interrupts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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-man" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux