Re: Add pselect, ppoll system calls.
David, > On Fri, 2005-08-05 at 14:49 +0200, Michael Kerrisk wrote: > > If I change your program to do something like the above, I also > > do not see a message from the handler -- i.e., it is not being > > called, and I'm pretty sure it should be. > > Hm, yes. What happens is we come back out of the select() immediately > because of the pending signal, but on the way back to userspace we put the > old signal mask back... so by the time we check for it, there _is_ no > (unblocked) signal pending. > > If it's mandatory that we actually call the signal handler, I'm just about to go off on holiday, and don't have a chance to pull up all the relevant standards details at them moment. However, I'm fairly sure that the signal handler should be called. (Try running a modified version of my program on Solaris 10 or the Unix-03 conversion of AIX (5.3?).) > then we need to > play tricks like sigsuspend() does to leave the old signal mask on the > stack frame. That's a bit painful atm because do_signal is different > between architectures. Yes, I'd say the behaviour should in fact be like what sigsuspend() does. Cheers, Michael - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Add pselect, ppoll system calls.
David, On Fri, 2005-08-05 at 14:49 +0200, Michael Kerrisk wrote: If I change your program to do something like the above, I also do not see a message from the handler -- i.e., it is not being called, and I'm pretty sure it should be. Hm, yes. What happens is we come back out of the select() immediately because of the pending signal, but on the way back to userspace we put the old signal mask back... so by the time we check for it, there _is_ no (unblocked) signal pending. If it's mandatory that we actually call the signal handler, I'm just about to go off on holiday, and don't have a chance to pull up all the relevant standards details at them moment. However, I'm fairly sure that the signal handler should be called. (Try running a modified version of my program on Solaris 10 or the Unix-03 conversion of AIX (5.3?).) then we need to play tricks like sigsuspend() does to leave the old signal mask on the stack frame. That's a bit painful atm because do_signal is different between architectures. Yes, I'd say the behaviour should in fact be like what sigsuspend() does. Cheers, Michael - To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: Add pselect, ppoll system calls.
David Woodhouse wrote: > If it's mandatory that we actually call the signal handler, then we need > to play tricks like sigsuspend() does to leave the old signal mask on > the stack frame. That's a bit painful atm because do_signal is different > between architectures. It is necessary that the handler is called. This is the purpose of these interfaces. If this means more complexity is needed then this is how the cookie crumbles. One use case for pselect would be something like this: int got_signal; void sigint_handler(int sig) { got_signal = 1; } { ... while (1) { if (!got_signal) pselect() if (got_signal) { handle signal got_signal = 0; } } ... } -- ➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖ signature.asc Description: OpenPGP digital signature
Re: Add pselect, ppoll system calls.
David Woodhouse wrote: If it's mandatory that we actually call the signal handler, then we need to play tricks like sigsuspend() does to leave the old signal mask on the stack frame. That's a bit painful atm because do_signal is different between architectures. It is necessary that the handler is called. This is the purpose of these interfaces. If this means more complexity is needed then this is how the cookie crumbles. One use case for pselect would be something like this: int got_signal; void sigint_handler(int sig) { got_signal = 1; } { ... while (1) { if (!got_signal) pselect() if (got_signal) { handle signal got_signal = 0; } } ... } -- ➧ Ulrich Drepper ➧ Red Hat, Inc. ➧ 444 Castro St ➧ Mountain View, CA ❖ signature.asc Description: OpenPGP digital signature
Re: Add pselect, ppoll system calls.
> From: David Woodhouse <[EMAIL PROTECTED]> > Subject: Re: Add pselect, ppoll system calls. > Date: Wed, 15 Jun 2005 12:36:54 +0100 > > On Mon, 2005-06-13 at 08:38 -0700, Ulrich Drepper wrote: > > > Eep -- I hadn't noticed that difference. Will update patch > > accordingly. > > > > And change [the poll timeout] to expect a 64bit value I hope... > > I believe that 64-bit int types in syscalls are a pain on some > architectures because of restrictions on precisely which register pairs > may be used. I think I'd rather just use a struct timespec, which also > makes it consistent with pselect(). > > > > The other documented difference (other than the signal mask bit) is > > > that > > > pselect() is documented not to modify the timeout parameter. I'm not > > > sure whether I should preserve that difference, or not. > > > > As long as there is a configuration where the timeout value is not > > modified, it doesn't matter. That is the case for select() using a > > personality switch. > > I've made pselect() consistent with select() by using the same > personality switch to control its behaviour. > > I've also fixed select() so that timeouts of greater than LONG_MAX > jiffies are implemented accurately, instead of being infinite. Hi David, I applied the 15 Jun version of your patch agains 2.6.12 and tried a test program. I see some behaviour that puzzles me. When I run the program below, and type control-C, the program tells me that the SIGINT hander was *not* called: ./t_pselect - Making syscall(SYS_pselect6) call [Type ^C] pselect: Unknown error 514 <-- ERESTNOHAND ready = -1 stdin IS NOT readable signal handler WAS NOT called I'm not sure whether this is possibly a mistake in the way I've constructed my test program (I don't think so, but I'm not !00% confident), or some bug in the implementation (I did try making a syscall(SYS__newselect), and that *did* show the signal handler being called. Also, I now have a test result on Solaris 10 for pselect(), and it shows the signal handler is called in this case.) Cheers, Michael /* t_pselect.c Michael Kerrisk, Aug 2005 */ #if defined(__linux__) && !defined(NO_SYSCALL) #define USE_PSELECT_SYSCALL 1 #endif #ifdef USE_PSELECT_SYSCALL #define _GNU_SOURCE #include #endif #include #include #include #include #include #include #include #include #include #define errMsg(msg) do { perror(msg); } while (0) #define errExit(msg)do { perror(msg); exit(EXIT_FAILURE); \ } while (0) #ifdef USE_PSELECT_SYSCALL /* Following are for x86 */ #define SYS_pselect6 289 #define SYS_ppoll 290 #endif sig_atomic_t gotsig = 0; static void handler(int sig) { gotsig = 1; printf("Caught signal %d\n", sig); /* UNSAFE (see Section $$$) */ } /* handler */ int main(int argc, char *argv[]) { fd_set readfds; int ready, nfds; struct timespec timeout; struct timespec *pto; struct sigaction sa; #ifdef USE_PSELECT_SYSCALL struct { sigset_t *sp; size_t size; } pselarg6; #endif sigset_t empty, all; if (argc != 2) { fprintf(stderr, "Usage: %s {nsecs|-}\n", argv[1]); exit(EXIT_FAILURE); } setbuf(stdout, NULL); /* Block all sigs */ sigfillset(); if (sigprocmask(SIG_BLOCK, , NULL) == -1) errExit("sigprocmask"); /* Establish hander for SIGINT */ sa.sa_handler = handler; sigemptyset(_mask); sa.sa_flags = 0; if (sigaction(SIGINT, , NULL) == -1) errExit("sigaction"); /* Timeout is specified in argv[1] */ if (strcmp(argv[1], "-") == 0) { pto = NULL; /* Infinite timeout */ } else { pto = timeout.tv_sec = atoi(argv[1]); timeout.tv_nsec = 0; } /* Initialize descriptor set */ nfds = 1; FD_ZERO(); FD_SET(STDIN_FILENO, ); sigemptyset(); /* sigaddset(, SIGINT); */ /* Make the call */ #ifdef USE_PSELECT_SYSCALL #if 1 printf("Making syscall(SYS_pselect6) call\n"); pselarg6.sp = pselarg6.size = 8; /* sizeof(sigset_t) */ ready = syscall(SYS_pselect6, nfds, , NULL, NULL, pto, ); #else /* The following is just some testing cruft */ { struct timeval tv; struct timeval *ptv; if (strcmp(argv[1], "-") == 0) { ptv = NULL; /* Infinite timeout */ } else { ptv = tv.tv_sec = atoi(argv[1]); tv.tv_usec = 0; } if (sigprocmask(SIG_SETMASK, , NULL) == -1) errExit("sigprocmask"); printf("Making syscall(SYS__newselect) call\n"); ready = syscall(SYS__newselect, nfds, , NULL, NULL, ptv); printf(" Ignore timeout informati
Re: Add pselect, ppoll system calls.
From: David Woodhouse [EMAIL PROTECTED] Subject: Re: Add pselect, ppoll system calls. Date: Wed, 15 Jun 2005 12:36:54 +0100 On Mon, 2005-06-13 at 08:38 -0700, Ulrich Drepper wrote: Eep -- I hadn't noticed that difference. Will update patch accordingly. And change [the poll timeout] to expect a 64bit value I hope... I believe that 64-bit int types in syscalls are a pain on some architectures because of restrictions on precisely which register pairs may be used. I think I'd rather just use a struct timespec, which also makes it consistent with pselect(). The other documented difference (other than the signal mask bit) is that pselect() is documented not to modify the timeout parameter. I'm not sure whether I should preserve that difference, or not. As long as there is a configuration where the timeout value is not modified, it doesn't matter. That is the case for select() using a personality switch. I've made pselect() consistent with select() by using the same personality switch to control its behaviour. I've also fixed select() so that timeouts of greater than LONG_MAX jiffies are implemented accurately, instead of being infinite. Hi David, I applied the 15 Jun version of your patch agains 2.6.12 and tried a test program. I see some behaviour that puzzles me. When I run the program below, and type control-C, the program tells me that the SIGINT hander was *not* called: ./t_pselect - Making syscall(SYS_pselect6) call [Type ^C] pselect: Unknown error 514 -- ERESTNOHAND ready = -1 stdin IS NOT readable signal handler WAS NOT called I'm not sure whether this is possibly a mistake in the way I've constructed my test program (I don't think so, but I'm not !00% confident), or some bug in the implementation (I did try making a syscall(SYS__newselect), and that *did* show the signal handler being called. Also, I now have a test result on Solaris 10 for pselect(), and it shows the signal handler is called in this case.) Cheers, Michael /* t_pselect.c Michael Kerrisk, Aug 2005 */ #if defined(__linux__) !defined(NO_SYSCALL) #define USE_PSELECT_SYSCALL 1 #endif #ifdef USE_PSELECT_SYSCALL #define _GNU_SOURCE #include syscall.h #endif #include sys/time.h #include sys/select.h #include signal.h #include sys/types.h #include stdio.h #include stdlib.h #include unistd.h #include string.h #include errno.h #define errMsg(msg) do { perror(msg); } while (0) #define errExit(msg)do { perror(msg); exit(EXIT_FAILURE); \ } while (0) #ifdef USE_PSELECT_SYSCALL /* Following are for x86 */ #define SYS_pselect6 289 #define SYS_ppoll 290 #endif sig_atomic_t gotsig = 0; static void handler(int sig) { gotsig = 1; printf(Caught signal %d\n, sig); /* UNSAFE (see Section $$$) */ } /* handler */ int main(int argc, char *argv[]) { fd_set readfds; int ready, nfds; struct timespec timeout; struct timespec *pto; struct sigaction sa; #ifdef USE_PSELECT_SYSCALL struct { sigset_t *sp; size_t size; } pselarg6; #endif sigset_t empty, all; if (argc != 2) { fprintf(stderr, Usage: %s {nsecs|-}\n, argv[1]); exit(EXIT_FAILURE); } setbuf(stdout, NULL); /* Block all sigs */ sigfillset(all); if (sigprocmask(SIG_BLOCK, all, NULL) == -1) errExit(sigprocmask); /* Establish hander for SIGINT */ sa.sa_handler = handler; sigemptyset(sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGINT, sa, NULL) == -1) errExit(sigaction); /* Timeout is specified in argv[1] */ if (strcmp(argv[1], -) == 0) { pto = NULL; /* Infinite timeout */ } else { pto = timeout; timeout.tv_sec = atoi(argv[1]); timeout.tv_nsec = 0; } /* Initialize descriptor set */ nfds = 1; FD_ZERO(readfds); FD_SET(STDIN_FILENO, readfds); sigemptyset(empty); /* sigaddset(empty, SIGINT); */ /* Make the call */ #ifdef USE_PSELECT_SYSCALL #if 1 printf(Making syscall(SYS_pselect6) call\n); pselarg6.sp = empty; pselarg6.size = 8; /* sizeof(sigset_t) */ ready = syscall(SYS_pselect6, nfds, readfds, NULL, NULL, pto, pselarg6); #else /* The following is just some testing cruft */ { struct timeval tv; struct timeval *ptv; if (strcmp(argv[1], -) == 0) { ptv = NULL; /* Infinite timeout */ } else { ptv = tv; tv.tv_sec = atoi(argv[1]); tv.tv_usec = 0; } if (sigprocmask(SIG_SETMASK, empty, NULL) == -1) errExit(sigprocmask); printf(Making syscall(SYS__newselect) call\n); ready = syscall(SYS__newselect, nfds, readfds, NULL, NULL, ptv); printf( Ignore timeout information printed below \n); } #endif #else /* This is how a proper pselect() call looks on other implementations, or when calling