Re: The Links/Links2/ELinks browsers are unusable on Debian GNU/Hurd

Fabienne Ducroquet <[email protected]>
Newsgroups gmane.comp.web.links,gmane.linux.debian.ports.hurd
Message-ID <[email protected]>
On Thu, Dec 20, 2007 at 06:29:51AM +0200, Kalle Olavi Niemitalo wrote:
> > 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) {
> 
> Recompile without optimization to see what really happens here.

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

Breakpoint 1, itrm_queue_event (itrm=0x81a1f40, data=0x1020b18 "", len=320)
    at kbd.c:112
112		int w = 0;
(gdb) n
114		if (!len) return;
(gdb) n
116		if (!itrm->out.queue.len && can_write(itrm->out.sock)) {
(gdb) n
124		if (w < len) {
(gdb) n
125			int left = len - w;
(gdb) n
126			unsigned char *c = mem_realloc(itrm->out.queue.data,
(gdb) n
129			if (!c) {
(gdb) n
134			itrm->out.queue.data = c;
(gdb) n
135			memcpy(itrm->out.queue.data + itrm->out.queue.len, data + w, left);
(gdb) n
136			itrm->out.queue.len += left;
(gdb) n
137			set_handlers(itrm->out.sock,
(gdb) n
142	}
(gdb) n
handle_trm (std_in=0, std_out=1, sock_in=1, sock_out=7, ctl_in=0, 
    init_string=0x81a1dd0, init_len=0, remote=0) at kbd.c:345
345		itrm_queue_event(itrm, (char *) init_string, init_len);

    The test line 116 fails here and not on Linux.  I still don't
understand why gdb says that it goes to the line 119
(check_bottom_halves) with optimization?
    With a breakpoint at can_read_or_write:

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

Breakpoint 1, itrm_queue_event (itrm=0x81a1f40, data=0x1020b18 "", len=320)
    at kbd.c:112
112		int w = 0;
(gdb) n
114		if (!len) return;
(gdb) n
116		if (!itrm->out.queue.len && can_write(itrm->out.sock)) {
(gdb) print *itrm
$1 = {in = {std = 0, sock = 1, ctl = 0, queue = {data = 0x81a1fd0 "", 
      len = 0}}, out = {std = 1, sock = 7, queue = {data = 0x0, len = 0}}, 
  timer = 0x0, t = {c_iflag = 10240, c_oflag = 3, c_cflag = 19201, 
    c_lflag = 4194499, c_cc = "\004ÿÿ\177\027\025\022ÿ\003ÿÿÿÿÿÿÿ\001\000ÿÿ", 
    __ispeed = 38400, __ospeed = 38400}, mouse_h = 0x0, orig_title = 0x0, 
  blocked = 0, altscreen = 1, touched_title = 0, remote = 0}
(gdb) n

Breakpoint 2, can_read_or_write (fd=7, write=1) at select.c:319
319		struct timeval tv = {0, 0};
(gdb) n
321		fd_set *rfds = NULL;
(gdb) n
322		fd_set *wfds = NULL;
(gdb) n
324		FD_ZERO(&fds);
(gdb) n
325		FD_SET(fd, &fds);
(gdb) n
327		if (write)
(gdb) n
328			wfds = &fds;
(gdb) n
332		return select(fd + 1, rfds, wfds, NULL, &tv);
(gdb) print wfds
$2 = (fd_set *) 0x1020a6c
(gdb) print rfds
$3 = (fd_set *) 0x0
(gdb) print &tv
$4 = (struct timeval *) 0x1020a8c
(gdb) print select(8,0x0,0x1020a6c,0x0,0x1020a8c)
$5 = 0
(gdb) n
333	}
(gdb) n
can_write (fd=7) at select.c:345
345	}
(gdb) n
itrm_queue_event (itrm=0x81a1f40, data=0x1020b18 "", len=320) at kbd.c:124
124		if (w < len) {
(gdb) n
125			int left = len - w;

> I mean, the compiler might merely have decided to load the
> address of free_itrm into a register at that point, or something
> like that.

    But how could I see that?

> > As you can see, there is something wrong there,
> 
> I don't see that.

    You are probably more experienced than me in that sort of thing, for
me that seems at least very weird. :-)

> So the patch doesn't reveal anything.

   It's true, I had not observed enough what it does.

> Instead, you should find out why the select function is reporting
> an exceptional state for the file descriptor.

   According to the gdb output above select in can_read_or_write(7,1)
returns 0 whereas on Linux it returns 1 in the same conditions, but why,
I don't know.

> I suggest you use rpctrace to find whether any io_select is
> returning the SELECT_URG flag in select_type, and from which
> server that reply comes. 

    I tried rpctrace elinks but I don't know what to look for in the
output...  There are lines such as:

task2573->vm_deallocate (21331968 4096) = 0 
  88->io_select_request (2)task2573->mach_port_destroy (pn{ 25}) = 0 
reply(94:io_select_request)->io_select_reply (0 2);
  72->io_write_request ("^[[1;1H" -1) = 0 6
  52->io_select_request (5)task2573->mach_port_allocate (3) = 0 pn{ 29}
task2573->mach_port_move_member (pn{ 25} pn{ 29}) = 0 
  86->io_select_request (5)task2573->mach_port_move_member (pn{ 27} pn{ 29}) = 0 
  88->io_select_request (6)task2573->mach_port_move_member (pn{ 28} pn{ 29}) = 0 
reply(96:io_select_request)->io_select_reply (0 2);
task2573->mach_port_destroy (pn{ 25}) = 0 

    What must I look here?  the numbers between parenthesis after
io_select_reply (in that case, they are always (0 1) or (0 2) or (0 0))?
something completely different?

> Also try putting the NULLs in ELinks
> like I mentioned in the previous message.

Something like the following patch?  It seems to work, but perhaps it
breaks something else.

Fabienne.

diff --git a/src/main/select.c b/src/main/select.c
index aab5349..7311c6f 100644
--- a/src/main/select.c
+++ b/src/main/select.c
@@ -33,6 +33,7 @@
 #include "main/select.h"
 #include "main/timer.h"
 #include "osdep/signals.h"
+#include "terminal/kbd.h"
 #include "terminal/terminal.h"
 #include "util/error.h"
 #include "util/memory.h"
@@ -148,7 +149,9 @@ set_handlers(int fd, select_handler_T read_func, select_handler_T write_func,
 #endif
 	threads[fd].read_func = read_func;
 	threads[fd].write_func = write_func;
-	threads[fd].error_func = error_func;
+	threads[fd].error_func = NULL;
+	if (error_func != (select_handler_T) free_itrm)
+		threads[fd].error_func = error_func;
 	threads[fd].data = data;
 
 	if (read_func) {
diff --git a/src/terminal/kbd.c b/src/terminal/kbd.c
index 1d34232..c2ff503 100644
--- a/src/terminal/kbd.c
+++ b/src/terminal/kbd.c
@@ -43,7 +43,6 @@
 
 struct itrm *ditrm = NULL;
 
-static void free_itrm(struct itrm *);
 static void in_kbd(struct itrm *);
 static void in_sock(struct itrm *);
 static int process_queue(struct itrm *);
@@ -397,7 +396,7 @@ block_itrm(void)
 }
 
 
-static void
+void
 free_itrm(struct itrm *itrm)
 {
 	if (!itrm) return;
diff --git a/src/terminal/kbd.h b/src/terminal/kbd.h
index e886f8c..bf95976 100644
--- a/src/terminal/kbd.h
+++ b/src/terminal/kbd.h
@@ -121,6 +121,7 @@ void itrm_queue_event(struct itrm *itrm, unsigned char *data, int len);
 void block_itrm(void);
 int unblock_itrm(void);
 void free_all_itrms(void);
+void free_itrm(struct itrm *);
 void resize_terminal(void);
 void dispatch_special(unsigned char *);
 void kbd_ctrl_c(void);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.