I think I've found the problem with fetching stylesheets that has been
reported by several users recently.
To reproduce, change max_fetches_per_host to 1 (options.c), then
gdb ./nsdebug, file:/home/james/Projects/netsurf/!NetSurf/Docs/intro_en,faf.
NetSurf starts infinite looping in html_find_stylesheets(). Interrupting
gives this backtrace:
#0 0x00002acc9edebd10 in __write_nocancel () from /lib/libc.so.6
#1 0x00002acc9ed93d53 in _IO_new_file_write () from /lib/libc.so.6
#2 0x00002acc9ed93c66 in _IO_new_do_write () from /lib/libc.so.6
#3 0x00002acc9ed9430c in _IO_new_file_overflow () from /lib/libc.so.6
#4 0x00002acc9ed90f3b in fputc () from /lib/libc.so.6
#5 0x0000000000406fab in fetch_dispatch_jobs () at content/fetch.c:349
#6 0x0000000000407534 in fetch_poll () at content/fetch.c:463
#7 0x0000000000437ed7 in html_find_stylesheets (c=0x5f9238, head=0x61b800) at
render/html.c:900
#8 0x00000000004368bd in html_convert (c=0x5f9238, width=1000, height=1000)
at render/html.c:445
#9 0x00000000004053a1 in content_convert (c=0x5f9238, width=1000,
height=1000) at content/content.c:739
#10 0x0000000000408f03 in fetchcache_callback (msg=FETCH_FINISHED, p=0x5f9238,
data=0x7fff0cc47ea0, size=0) at content/fetchcache.c:431
#11 0x0000000000407721 in fetch_send_callback (msg=FETCH_FINISHED,
fetch=0x5f9780, data=0x7fff0cc47ea0, size=0) at content/fetch.c:544
#12 0x000000000041311c in fetch_curl_done (curl_handle=0x5f9ab0,
result=CURLE_OK) at content/fetchers/fetch_curl.c:815
#13 0x0000000000412e9f in fetch_curl_poll (scheme_ignored=0x5dc020 "ftps") at
content/fetchers/fetch_curl.c:735
#14 0x0000000000407555 in fetch_poll () at content/fetch.c:469
#15 0x0000000000462b9d in main (argc=1, argv=0x7fff0cc484a8) at
debug/netsurfd.c:90
At this point fetch_ring and queue_ring are:
queue_ring:
file:///home/james/Projects/netsurf/ns.css
file:///home/james/Projects/netsurf/!NetSurf/Docs/netsurf
fetch_ring
file:///home/james/Projects/netsurf/!NetSurf/Docs/intro_en,faf
Since max_fetches_per_host is 1, the queued fetches are waiting for the
current fetch to stop, but this won't happen until fetch_curl_done()
finishes.
The cause of this is that fetch_curl_stop() (previously fetch_stop()) was
moved to be after the callbacks in fetch_curl_done() (previously
fetch_done()):
svn diff
svn://svn.netsurf-browser.org/trunk/netsurf/content/fetch.c@3307
svn://svn.netsurf-browser.org/trunk/netsurf/content/fetchers/fetch_curl.c
-void fetch_done(CURL *curl_handle, CURLcode result)
+static void fetch_curl_done(CURL *curl_handle, CURLcode result)
{
bool finished = false;
bool error = false;
...
- /* clean up fetch and start any queued fetch for this host */
- fetch_stop(f);
-
/* postponed until after stop so that queue fetches are started */
if (abort)
; /* fetch was aborted: no callback */
else if (finished) {
...
+
+ fetch_curl_stop(f);
}
The comment that indicates why stop was at that point is still there.
I tried moving the call to fetch_curl_stop() back, but it was moved for the
reason that it now deallocates some memory used after the old position.
I guess the solution is to split fetch_curl_stop() into two parts, one to
remove the fetch from the active fetches (fetch_ring), and the second to free
it.
The fetch code is getting very complex and I think we need to simplify it if
possible. This was the case already before the split into fetch and
fetch_curl. We probably need to reconsider if the architecture based on
callbacks is the best way.
James
--
James Bursa, NetSurf developer
http://www.netsurf-browser.org/