Re: signals and atomicity

1998-04-23 Thread Herbert Xu
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

1998-04-23 Thread erikyyy
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

1998-04-23 Thread Roman Hodek

 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

1998-04-23 Thread erikyyy
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

1998-04-19 Thread erikyyy
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

1998-04-19 Thread Rob Browning
[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

1998-04-18 Thread Herbert Xu
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

1998-04-17 Thread erikyyy
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

1998-04-17 Thread Rob Browning
[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]