[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 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);


Reply to: