On Sun, 23 Jan 2005, ierdnah wrote:
> 
> (gdb) disassemble pty_chars_in_buffer
...
> 0xc02c97a7 <pty_chars_in_buffer+23>:    mov    0x28(%edx),%ecx **
> 0xc02c97aa <pty_chars_in_buffer+26>:    test   %ecx,%ecx
> 0xc02c97ac <pty_chars_in_buffer+28>:    jne    0xc02c97b6
> 0xc02c97ae <pty_chars_in_buffer+30>:    mov    0x4(%esp,1),%ebx
> 0xc02c97b2 <pty_chars_in_buffer+34>:    add    $0x8,%esp
> 0xc02c97b5 <pty_chars_in_buffer+37>:    ret
> 0xc02c97b6 <pty_chars_in_buffer+38>:    mov    %edx,(%esp,1)
> 0xc02c97b9 <pty_chars_in_buffer+41>:    call   *0x28(%edx) **

Ahh, indeed. When I compiled this function, it kept 0x28(%edx) in a 
register. Your config/compiler combination does not, so there actually is 
a race condition if somebody changes the function pointer.

> this is another compiled kernel, but is compiled with the same .config
> file and same gcc version...because I only have the bzImage, how do I
> convert it to vmlinux?

Don't worry, it clearly shows that it's at least possible, and worth 
looking at. 

For testing, a patch like this might get rid of the problem by hiding the
race (but for all I know, gcc ends up re-loading it anyway) - you might 
want to check the disassembly. 

However, this patch is just for testing, to verify that your problem 
really is that particular race. It's not a proper fix.

I suspect that pty's should always lock each others line disciplines too, 
not just their "own" side.

                Linus

----
--- 1.32/drivers/char/pty.c     2005-01-10 17:29:36 -08:00
+++ edited/drivers/char/pty.c   2005-01-23 09:49:16 -08:00
@@ -149,13 +149,15 @@
 static int pty_chars_in_buffer(struct tty_struct *tty)
 {
        struct tty_struct *to = tty->link;
+       ssize_t (*chars_in_buffer)(struct tty_struct *);
        int count;
 
-       if (!to || !to->ldisc.chars_in_buffer)
+       /* We should get the line discipline lock for "tty->link" */
+       if (!to || !(chars_in_buffer = to->ldisc.chars_in_buffer))
                return 0;
 
        /* The ldisc must report 0 if no characters available to be read */
-       count = to->ldisc.chars_in_buffer(to);
+       count = chars_in_buffer(to);
 
        if (tty->driver->subtype == PTY_TYPE_SLAVE) return count;
 
-
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/

Reply via email to