public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Register saving and signal handling
@ 2005-01-25 20:16 Robert Szeleney
  2005-01-25 21:26 ` linux-os
  0 siblings, 1 reply; 2+ messages in thread
From: Robert Szeleney @ 2005-01-25 20:16 UTC (permalink / raw)
  To: linux-kernel

Hi!

This is my first time posting to the Linux kernel mailing-list, and I 
hope someone can help me or at least explain following to me.

When a task gets interrupted by a signal, the do_signal() function is 
called. Now, when the signal is not handled by the task and the 
interrupted function returned -EINTR, the syscall gets restarted by 
modifying the user mode EIP to point to the int 0x80 again.

When the task leaves the do_signal function, it will pop the saved 
registers and return to the user mode and immediately do the syscall again.

But now to the actual question:

Let's make a new "test" system call function. Let's call it: sys_test

asmlinkage int sys_test(int para1, int para2)
{
    para1++;
    para2++;

    kill( current->pid, SIGCHLD);
    return -EINTR;
}

When compiling this function, GCC increments para1 and para2 by one. 
para1 and para2 are stored on the kernel stack. The system call entry 
assembler function pushed the registers containing this values from the 
usermode on the stack.
But GCC actually modified the values on the stack here, the "live" data. 
(which will be poped later again, right before returning to user mode)

After returning from this function, the system call wrapper checks for a 
signal and calls do_signal. The do_signal call will restart the system 
call by modifying the user mode EIP. Then, the system call wrapper will 
pop the saved registers from the stack. But here I see this problem. The 
already modified values for para1 and para2 will be popped. When the 
system call is then start again, para1 and para2 don't have to original 
value.

One can say, why are you modifying para1 and para2 then?  Yes, this is 
correct, but after compiling a few more test sources, I got following 
problem:

asmlinkage int sys_test(int iSize)
{
     printk("Size is: %d\n", iSize * sizeof(any_structure));
}

When compiling this, GCC produces following assembler:

....
sall    $4, 8(%ebp)
....

which actually modifies the content of the stack holding the iSize 
again. It is very difficult to keep track of such implicit stack 
argument modifications.
Thus, when a signal is waiting and the syscall is restarted, iSize 
contains a different value already.

So, does anyone else have such a problem? Is there any compiler flag 
missing? Is this possible at all?

Thank you very much!
Robert!

Btw,  please CC to mf204005@liwest.at  too.







^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-01-25 21:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-25 20:16 Register saving and signal handling Robert Szeleney
2005-01-25 21:26 ` linux-os

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox