Re: signals and atomicity
In article [EMAIL PROTECTED] you wrote: On Sat, 18 Apr 1998, Herbert Xu wrote: This should work: static int wait_or_timeout_retval = -1; static void alarm_handler(int sig) { errno = ETIMEDOUT; } int wait_or_timeout (int *status) { struct sigaction act; wait_or_timeout_retval = -1; sigaction(SIGALRM, 0, act); act.sa_handler = alarm_handler; act.sa_flags = ~SA_RESTART; sigaction(SIGALRM, act, 0); alarm(1); wait_or_timeout_retval = wait(status); alarm(0); return wait_or_timeout_retval; } i do not think, this works. alarm() calls setitimer(). setitimer() modifies errno. so, setting errno inside the signal handler does not work, i think. That's easy to fix. Just store ETIMEDOUT in some other variable that is reset at the start of wait_or_timeout and store the result in errno if wait fails with EINTR. -- Debian GNU/Linux 1.3 is out! ( http://www.debian.org/ ) Email: Herbert Xu ~{PmVHI~} [EMAIL PROTECTED] Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: signals and atomicity
On Thu, 23 Apr 1998, Herbert Xu wrote: In article [EMAIL PROTECTED] you wrote: On Sat, 18 Apr 1998, Herbert Xu wrote: This should work: static int wait_or_timeout_retval = -1; static void alarm_handler(int sig) { errno = ETIMEDOUT; } int wait_or_timeout (int *status) { struct sigaction act; wait_or_timeout_retval = -1; sigaction(SIGALRM, 0, act); act.sa_handler = alarm_handler; act.sa_flags = ~SA_RESTART; sigaction(SIGALRM, act, 0); alarm(1); wait_or_timeout_retval = wait(status); alarm(0); return wait_or_timeout_retval; } i do not think, this works. alarm() calls setitimer(). setitimer() modifies errno. so, setting errno inside the signal handler does not work, i think. That's easy to fix. Just store ETIMEDOUT in some other variable that is reset at the start of wait_or_timeout and store the result in errno if wait fails with EINTR. this way you can fix the problem. but my initial problem was different: 2 processes. if (1) does a specific call (probably raising a signal), B's next interruptible (whatever this means) system call must be interrupted. the fact that (1) raised the signal mustn't get lost. if you implement interruptible system calls this way: 1. UNBLOCK SIGNAL 2. SYSTEM CALL 3. BLOCK SIGNAL it may happen that the signal handler is called just after unblocking the signal but before the call. this way no EINTR happens, the signal is lost and (2) is stuck in the system call. because of this, i have to do a siglongjmp() in the signal handler. now it isn't anymore possible that signals get lost. BUT ! i do not know the return value of the system call, if it was interrupted. remember, after the call , the signal is blocked again. now, if the call succeeded, but still before the BLOCK SIGNAL command, if now again a signal is received, siglongjmp jumps away, and the fact, that the system call succeeded is just lost. i am looking for an atomic way for a process to interrupt another processes next system call, __that is marked as interruptible (whatever this means)__. the interrupt __mustn't get lost__. afterwards i must always know, wether the system call succeeded, or not. i find no way of doing it. this is why i said the whole system is shi. i am sorry about this sentence, but i was in a very bad mood, because for weeks i try to solve this thing and i do not succeed. byebye Erik -- EMAIL: [EMAIL PROTECTED] [EMAIL PROTECTED] o `QQ'_ IRC: erikyyy/ __8 WWW: http://wwwcip.rus.uni-stuttgart.de/~inf24628/ ' ` http://tick.informatik.uni-stuttgart.de/~thieleek/ -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: signals and atomicity
if you implement interruptible system calls this way: 1. UNBLOCK SIGNAL 2. SYSTEM CALL 3. BLOCK SIGNAL it may happen that the signal handler is called just after unblocking the signal but before the call. this way no EINTR happens, the signal is lost and (2) is stuck in the system call. because of this, i have to do a siglongjmp() in the signal handler. now it isn't anymore possible that signals get lost. BUT ! i do not know the return value of the system call, if it was interrupted. remember, after the call , the signal is blocked again. now, if the call succeeded, but still before the BLOCK SIGNAL command, if now again a signal is received, siglongjmp jumps away, and the fact, that the system call succeeded is just lost. You can solve it this way (at least I hope... :-) : static int timeout; static void alarm_handler(int sig) { timeout = 1; } int wait_or_timeout (int *status) { struct sigaction act; int wait_retval; timeout = 0; sigaction(SIGALRM, 0, act); act.sa_handler = alarm_handler; act.sa_flags = ~SA_RESTART; sigaction(SIGALRM, act, 0); alarm(1); wait_retval = wait(status); alarm(0); /* ... */ } If 'timeout' is set at the end, SIGALRM was delivered before the alarm(0). On the other hand, wait_retval is -EINTR if and only if the system call itself has been interrupted. So you can distinguish between the cases system call interrupted and signal arrived, but somewhere around the syscall. Roman -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: signals and atomicity
On Thu, 23 Apr 1998, Roman Hodek wrote: if you implement interruptible system calls this way: 1. UNBLOCK SIGNAL 2. SYSTEM CALL 3. BLOCK SIGNAL it may happen that the signal handler is called just after unblocking the signal but before the call. this way no EINTR happens, the signal is lost and (2) is stuck in the system call. because of this, i have to do a siglongjmp() in the signal handler. now it isn't anymore possible that signals get lost. BUT ! i do not know the return value of the system call, if it was interrupted. remember, after the call , the signal is blocked again. now, if the call succeeded, but still before the BLOCK SIGNAL command, if now again a signal is received, siglongjmp jumps away, and the fact, that the system call succeeded is just lost. You can solve it this way (at least I hope... :-) : static int timeout; static void alarm_handler(int sig) { timeout = 1; } int wait_or_timeout (int *status) { struct sigaction act; int wait_retval; timeout = 0; sigaction(SIGALRM, 0, act); act.sa_handler = alarm_handler; act.sa_flags = ~SA_RESTART; sigaction(SIGALRM, act, 0); alarm(1); wait_retval = wait(status); alarm(0); /* ... */ } If 'timeout' is set at the end, SIGALRM was delivered before the alarm(0). On the other hand, wait_retval is -EINTR if and only if the system call itself has been interrupted. So you can distinguish between the cases system call interrupted and signal arrived, but somewhere around the syscall. no. this is no solution, because: once you activate the signal with sigaction, the sender might send a signal, and this one will be lost. so the thing that i wanted (i wanted that NO signal gets lost) does not work. the problem cannot be solved without using siglongjmp(). i am sure, the problem cannot be solved with this library+operating system :-( (or does anyone know some assembler hacks ?) byebye Erik -- EMAIL: [EMAIL PROTECTED] [EMAIL PROTECTED] o `QQ'_ IRC: erikyyy/ __8 WWW: http://wwwcip.rus.uni-stuttgart.de/~inf24628/ ' ` http://tick.informatik.uni-stuttgart.de/~thieleek/ -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: signals and atomicity
On Sat, 18 Apr 1998, Herbert Xu wrote: In article [EMAIL PROTECTED] you wrote: if the signal occurs after the wait system call, but before the result of the system call is stored in wait_or_timeout_retval, the fact, that the system call succeeded is lost. this is (1) a bug in apache and (2) a problem of me that i want to solve. i thought others would have solved it, but this is obviously not true :-( This should work: static int wait_or_timeout_retval = -1; static void alarm_handler(int sig) { errno = ETIMEDOUT; } int wait_or_timeout (int *status) { struct sigaction act; wait_or_timeout_retval = -1; sigaction(SIGALRM, 0, act); act.sa_handler = alarm_handler; act.sa_flags = ~SA_RESTART; sigaction(SIGALRM, act, 0); alarm(1); wait_or_timeout_retval = wait(status); alarm(0); return wait_or_timeout_retval; } i do not think, this works. alarm() calls setitimer(). setitimer() modifies errno. so, setting errno inside the signal handler does not work, i think. i think the whole system is shit. it cannot work this way. there is no single way to solve this problem with linux :-( i am very unhappy. again, this is what i want: thread A: calls signalthread_B. must return IMMEDIATELY. thread B: IF it just is inside a system call, this call must return EINTR. IF not, the NEXT system call that is marked as INTERRUPTIBLE (however this works) must return EINTR. what is this good for ? well. threads communicate through message queues. but B will not receive the message from A, if he is stuck in a system call. so A calls signalthread_B, if it is possible, that B ever gets locked in system calls. of course, ONLY system calls marked as INTERRUPTIBLE may return EINTR. (otherwise one would have to check the return code of EVERY system call. it is extremly important, that signalthread_B doesn't get lost, i.e. B just doesn't get the EINTR. byebye Erik -- EMAIL: [EMAIL PROTECTED] [EMAIL PROTECTED] o `QQ'_ IRC: erikyyy/ __8 WWW: http://wwwcip.rus.uni-stuttgart.de/~inf24628/ ' ` http://tick.informatik.uni-stuttgart.de/~thieleek/ -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: signals and atomicity
[EMAIL PROTECTED] writes: i think the whole system is shit. it cannot work this way. Nice temper. Not the best approach to getting help I've seen... there is no single way to solve this problem with linux :-( i am very unhappy. Apparently. what is this good for ? well. threads communicate through message queues. but B will not receive the message from A, if he is stuck in a system call. so A calls signalthread_B, if it is possible, that B ever gets locked in system calls. of course, ONLY system calls marked as INTERRUPTIBLE may return EINTR. (otherwise one would have to check the return code of EVERY system call. it is extremly important, that signalthread_B doesn't get lost, i.e. B just doesn't get the EINTR. Relying on EINTR like this is just broken. If you're that concerned about thread B getting woken up, you should be much more careful about using any blocking system calls, and yes, you *must* check the return code of *every* system call. Aside from the fact that you need it here, not doing so is just bad programming. You should probably be using select with a timeout instead of a blocking read, and if responsiveness is *really* critical, then you may need to restructure your program so that one thread is handling IO, and another is catching communications from thread A and doing the time-critical operations. Alternately, and perhaps even better, you could have two fd's. One is the normal one you're waiting on for data, and the other is a control fd. Have thread B issue a (blocking) select on both of them, and if you need to wake B up immediately, don't use signals (which don't have the best semantics in the face of threads), just send a byte on the control fd. -- Rob Browning [EMAIL PROTECTED] PGP fingerprint = E8 0E 0D 04 F5 21 A0 94 53 2B 97 F5 D6 4E 39 30 -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: signals and atomicity
In article [EMAIL PROTECTED] you wrote: if the signal occurs after the wait system call, but before the result of the system call is stored in wait_or_timeout_retval, the fact, that the system call succeeded is lost. this is (1) a bug in apache and (2) a problem of me that i want to solve. i thought others would have solved it, but this is obviously not true :-( This should work: static int wait_or_timeout_retval = -1; static void alarm_handler(int sig) { errno = ETIMEDOUT; } int wait_or_timeout (int *status) { struct sigaction act; wait_or_timeout_retval = -1; sigaction(SIGALRM, 0, act); act.sa_handler = alarm_handler; act.sa_flags = ~SA_RESTART; sigaction(SIGALRM, act, 0); alarm(1); wait_or_timeout_retval = wait(status); alarm(0); return wait_or_timeout_retval; } -- Debian GNU/Linux 1.3 is out! ( http://www.debian.org/ ) Email: Herbert Xu ~{PmVHI~} [EMAIL PROTECTED] Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
signals and atomicity
hi, i found the following code in apache web server code. if the signal occurs after the wait system call, but before the result of the system call is stored in wait_or_timeout_retval, the fact, that the system call succeeded is lost. this is (1) a bug in apache and (2) a problem of me that i want to solve. i thought others would have solved it, but this is obviously not true :-( now perhaps it is not interesting, wether the wait call succeeded, because you can start it again. but what about a call to read() ? i MUST know, wether it worked or wether it was interrupted by a signal! byebye Erik o snap static JMP_BUF wait_timeout_buf; static int wait_or_timeout_retval = -1; static void longjmp_out_of_alarm (int sig) { siglongjmp (wait_timeout_buf, 1); } int wait_or_timeout (int *status) { wait_or_timeout_retval = -1; if (sigsetjmp(wait_timeout_buf, 1) != 0) { errno = ETIMEDOUT; return wait_or_timeout_retval; } signal (SIGALRM, longjmp_out_of_alarm); alarm(1); wait_or_timeout_retval = wait(status); alarm(0); return wait_or_timeout_retval; } o--- snip -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Re: signals and atomicity
[EMAIL PROTECTED] writes: now perhaps it is not interesting, wether the wait call succeeded, because you can start it again. but what about a call to read() ? i MUST know, wether it worked or wether it was interrupted by a signal! Off the top of my head, if you issue a blocking read, and it gets interrupted, it will either return -1 and errno will be == EINTR or it will return the data already read. Hence you should always check to see if you got what you expected. If it's a non-blocking read, then the same applies, but you should definitely be equipped to handle partial reads (see the man page man 2 read for more info, or the libc info pages). Note that you can set things up so that interrupted system calls restart themselves rather than returning with an error, but I don't recall at the moment which function does that. -- Rob Browning [EMAIL PROTECTED] PGP fingerprint = E8 0E 0D 04 F5 21 A0 94 53 2B 97 F5 D6 4E 39 30 -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]