[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [elinks-dev] The Links/Links2/ELinks browsers are unusable on Debian GNU/Hurd



On Thu, Dec 20, 2007 at 12:40:10AM +0200, Kalle Olavi Niemitalo wrote:
> free_itrm should be called only if an error or EOF occurs in
> terminal handling, or when ELinks is exiting.

    Did you receive all my replies? I sent 3 successive replies through
gmane during my investigation but I see only one in elinks-dev web
archive.
    I did not detail what I've done in these mails, I will do that here
(it's rather long with the output of gdb, sorry).
    As threads[i].error_func is set by set_handlers, I've put a
breakpoint at set_handlers and compared what happens on Hurd and Linux
in the same conditions (run elinks -no-home about:blank on a terminal on
which I've done sleep 99999 and which I don't touch during the test).
On Linux set_handlers is called only 2 times before ELinks displays the
blank page I've requested and waits for further input, the result with
backtraces at each break is:

(gdb) run -no-home about:blank
Starting program: /home/fabi/prog/bin/elinks-bin -no-home about:blank
[Thread debugging using libthread_db enabled]
[New Thread 0xb737c930 (LWP 21627)]
[Switching to Thread 0xb737c930 (LWP 21627)]

Breakpoint 2, set_handlers (fd=0, read_func=0x8106ae0 <in_kbd>, write_func=0, 
    error_func=0x8105970 <free_itrm>, data=0x81c0d38) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=0, read_func=0x8106ae0 <in_kbd>, write_func=0, 
    error_func=0x8105970 <free_itrm>, data=0x81c0d38) at select.c:144
#1  0x0810565c in handle_itrm_stdin (itrm=<value optimized out>) at kbd.c:1193
#2  0x08105e19 in handle_trm (std_in=0, std_out=1, sock_in=1, sock_out=7, 
    ctl_in=0, init_string=0x82a69e8, init_len=12, remote=0) at kbd.c:330
#3  0x0810b59f in attach_terminal (in=0, out=1, ctl=0, info=0x82a69e8, len=12)
    at terminal.c:371
#4  0x080cf578 in init () at main.c:239
#5  0x080d0071 in select_loop (init=0x80cef20 <init>) at select.c:204
#6  0x080cf6b8 in main (argc=3, argv=0xbf945444) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=6, read_func=0x8104890 <in_term>, write_func=0, 
    error_func=0x810ae90 <destroy_terminal>, data=0x82f7e28) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=6, read_func=0x8104890 <in_term>, write_func=0, 
    error_func=0x810ae90 <destroy_terminal>, data=0x82f7e28) at select.c:144
#1  0x0810b452 in init_term (fdin=6, fdout=1) at terminal.c:101
#2  0x0810b5b3 in attach_terminal (in=0, out=1, ctl=0, info=0x82a69e8, len=12)
    at terminal.c:373
#3  0x080cf578 in init () at main.c:239
#4  0x080d0071 in select_loop (init=0x80cef20 <init>) at select.c:204
#5  0x080cf6b8 in main (argc=3, argv=0xbf945444) at main.c:361
(gdb) c
Continuing.


     On Hurd there are 9 calls to set_handlers before ELinks displays
the about:blank (and I have to kill gdb after that because it does not
understand ^C).  The result is:

(gdb) run -no-home about:blank
Starting program: /home/fabi/hurd/bin/elinks -no-home about:blank

Breakpoint 2, set_handlers (fd=0, read_func=0x80c1a10 <in_kbd>, write_func=0, 
    error_func=0x80c0970 <free_itrm>, data=0x8187f00) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=0, read_func=0x80c1a10 <in_kbd>, write_func=0, 
    error_func=0x80c0970 <free_itrm>, data=0x8187f00) at select.c:144
#1  0x080c06cb in handle_itrm_stdin (itrm=0x8187f00) at kbd.c:1193
#2  0x080c0d6a in handle_trm (std_in=0, std_out=1, sock_in=1, sock_out=7, 
    ctl_in=0, init_string=0x8187dd0, init_len=12, remote=0) at kbd.c:330
#3  0x080c5aeb in attach_terminal (in=0, out=1, ctl=0, info=0x8187dd0, len=12)
    at terminal.c:371
#4  0x0809de88 in init () at main.c:239
#5  0x0809e8f7 in select_loop (init=0x809d900 <init>) at select.c:204
#6  0x0809df98 in main (argc=) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=7, read_func=0, 
    write_func=0x80c1090 <itrm_queue_write>, error_func=0x80c0970 <free_itrm>, 
    data=0x8187f00) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=7, read_func=0, write_func=0x80c1090 <itrm_queue_write>, 
    error_func=0x80c0970 <free_itrm>, data=0x8187f00) at select.c:144
#1  0x080c0bd0 in itrm_queue_event (itrm=0x8187f00, data=0x1020b28 "", len=320)
    at kbd.c:137
#2  0x080c0dff in handle_trm (std_in=0, std_out=1, sock_in=1, sock_out=7, 
    ctl_in=0, init_string=0x8187dd0, init_len=12, remote=0) at kbd.c:344
#3  0x080c5aeb in attach_terminal (in=0, out=1, ctl=0, info=0x8187dd0, len=12)
    at terminal.c:371
#4  0x0809de88 in init () at main.c:239
	info = {magic = 777777777, source = 0x8187dd0 "about:blank", length = 12}
#5  0x0809e8f7 in select_loop (init=0x809d900 <init>) at select.c:204
#6  0x0809df98 in main (argc=) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=7, read_func=0, 
    write_func=0x80c1090 <itrm_queue_write>, error_func=0x80c0970 <free_itrm>, 
    data=0x8187f00) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=7, read_func=0, write_func=0x80c1090 <itrm_queue_write>, 
    error_func=0x80c0970 <free_itrm>, data=0x8187f00) at select.c:144
#1  0x080c0bd0 in itrm_queue_event (itrm=0x8187f00, data=0x8187dd0 "about:blank", 
    len=12) at kbd.c:137
#2  0x080c0e10 in handle_trm (std_in=0, std_out=1, sock_in=1, sock_out=7, 
    ctl_in=0, init_string=0x8187dd0, init_len=12, remote=0) at kbd.c:345
#3  0x080c5aeb in attach_terminal (in=0, out=1, ctl=0, info=0x8187dd0, len=12)
    at terminal.c:371
#4  0x0809de88 in init () at main.c:239
#5  0x0809e8f7 in select_loop (init=0x809d900 <init>) at select.c:204
#6  0x0809df98 in main (argc=) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=6, read_func=0x80bfab0 <in_term>, write_func=0, 
    error_func=0x80c53f0 <destroy_terminal>, data=0x8188180) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=6, read_func=0x80bfab0 <in_term>, write_func=0, 
    error_func=0x80c53f0 <destroy_terminal>, data=0x8188180) at select.c:144
#1  0x080c5981 in init_term (fdin=6, fdout=1) at terminal.c:101
#2  0x080c5afe in attach_terminal (in=0, out=1, ctl=0, info=0x8187dd0, len=12)
    at terminal.c:373
#3  0x0809de88 in init () at main.c:239
#4  0x0809e8f7 in select_loop (init=0x809d900 <init>) at select.c:204
#5  0x0809df98 in main (argc=0, argv=0x0) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=7, read_func=0, write_func=0, 
    error_func=0x80c0970 <free_itrm>, data=0x8187f00) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=7, read_func=0, write_func=0, 
    error_func=0x80c0970 <free_itrm>, data=0x8187f00) at select.c:144
#1  0x080c11dc in itrm_queue_write (itrm=0x8187f00) at kbd.c:97
#2  0x0809ea8b in select_loop (init=0x809d900 <init>) at select.c:297
#3  0x0809df98 in main (argc=) at main.c:361
(gdb) c
Continuing.

Breakpoint 1, free_itrm (itrm=0x8187f00) at kbd.c:403
403		if (!itrm) return;
(gdb) bt
#0  free_itrm (itrm=0x8187f00) at kbd.c:403
#1  0x0809eac9 in select_loop (init=0x809d900 <init>) at select.c:305
#2  0x0809df98 in main (argc=) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=0, read_func=0, write_func=0, error_func=0, 
    data=0x0) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=0, read_func=0, write_func=0, error_func=0, data=0x0)
    at select.c:144
#1  0x080c09c4 in free_itrm (itrm=0x8187f00) at kbd.c:431
#2  0x0809eac9 in select_loop (init=0x809d900 <init>) at select.c:305
#3  0x0809df98 in main (argc=0, argv=0x0) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=1, read_func=0, write_func=0, error_func=0, 
    data=0x0) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=1, read_func=0, write_func=0, error_func=0, data=0x0)
    at select.c:144
#1  0x080c09d8 in free_itrm (itrm=0x8187f00) at kbd.c:432
#2  0x0809eac9 in select_loop (init=0x809d900 <init>) at select.c:305
#3  0x0809df98 in main (argc=) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=1, read_func=0, write_func=0, error_func=0, 
    data=0x0) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=1, read_func=0, write_func=0, error_func=0, data=0x0)
    at select.c:144
#1  0x080c09ec in free_itrm (itrm=0x8187f00) at kbd.c:433
#2  0x0809eac9 in select_loop (init=0x809d900 <init>) at select.c:305
#3  0x0809df98 in main (argc=) at main.c:361
(gdb) c
Continuing.

Breakpoint 2, set_handlers (fd=7, read_func=0, write_func=0, error_func=0, 
    data=0x0) at select.c:144
144		assertm(fd >= 0 && fd < FD_SETSIZE,
(gdb) bt
#0  set_handlers (fd=7, read_func=0, write_func=0, error_func=0, data=0x0)
    at select.c:144
#1  0x080c0a00 in free_itrm (itrm=0x8187f00) at kbd.c:434
#2  0x0809eac9 in select_loop (init=0x809d900 <init>) at select.c:305
#3  0x0809df98 in main (argc=) at main.c:361
(gdb) c
Continuing.



    There is no problem with the first call to set_handlers (the same as
on Linux), but the second one comes from itrm_queue_event which does not
call set_handlers on Linux.  Then I put a breakpoint at itrm_queue_event
to compare its execution on Hurd and Linux, the part of code concerned
is (in src/terminal/kbd.c):

109 void
110 itrm_queue_event(struct itrm *itrm, unsigned char *data, int len)
111 {
112 	int w = 0;
113
114 	if (!len) return;
115
116 	if (!itrm->out.queue.len && can_write(itrm->out.sock)) {
117 		w = safe_write(itrm->out.sock, data, len);
118 		if (w <= 0 && HPUX_PIPE) {
119 			register_bottom_half(free_itrm, itrm);
120 			return;
121 		}
122 	}
123
124 	if (w < len) {
	...
141	}
142 }

set_handlers is called in the if, but there is no problem during the
execution of this part of code.  On Linux the line 117 is executed, then
the 2 tests (w <= 0 && HPUX_PIPE) and (w < len) fail (because w == len)
and the function exits. Here is what the step by step execution of this
function gives on Hurd:

(gdb) run -no-home about:blank
Starting program: /home/fabi/hurd/elinks/src/elinks -no-home about:blank

Breakpoint 1, itrm_queue_event (itrm=0x8187f00, data=0x1020b28 "", len=320)
    at kbd.c:114
114		if (!len) return;
(gdb) n
116		if (!itrm->out.queue.len && can_write(itrm->out.sock)) {
(gdb) n
119				register_bottom_half(free_itrm, itrm);
(gdb) n
124		if (w < len) {
(gdb) print w
$1 = 0

The execution continues normally, there is a if (!c) {
free_itrm(itrm);... but free_itrm is not executed yet because c<>0 here.
As you can see, there is something wrong there, and I think that it is
that which causes ELinks to call free_itrm later (and that at that
moment the call to free_itrm is justified).  And indeed, I've just tried
to cause the same behaviour on Linux by applying the following patch:

diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index 1d34232..5868062 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -114,11 +114,11 @@ itrm_queue_event(struct itrm *itrm, unsigned char *data, int len)
 	if (!len) return;
 
 	if (!itrm->out.queue.len && can_write(itrm->out.sock)) {
-		w = safe_write(itrm->out.sock, data, len);
-		if (w <= 0 && HPUX_PIPE) {
+/*		w = safe_write(itrm->out.sock, data, len);
+		if (w <= 0 && HPUX_PIPE) {*/
 			register_bottom_half(free_itrm, itrm);
-			return;
-		}
+		/*	return;
+		}*/
 	}
 
 	if (w < len) {

    The results are quite good, i.e. it breaks everything, though the
behaviour is not exactly the same as on Hurd (the screen remains blank
whereas on Hurd the page requested is displayed), there is a call to
free_itrm too.
    And now, I have no idea what causes the execution of itrm_queue_event
to be wrong.

> However, I don't know the origin of that code

    The function select_loop seems to mostly come directly from Links.
    I have no opinion for the rest of your e-mail, I did not understand :)

-- 
Fabienne


Reply to: