5digits / dactyl

Pentadactyl and other related Gecko extensions
Other
467 stars 98 forks source link

Firefox hangs when searching with / and a text input field is open, only when there's a match #206

Open afarah1 opened 7 years ago

afarah1 commented 7 years ago

Whenever I search with / and I have a page open which contains a text input field and there is a match, Firefox hangs. This did not happen on previous versions of Firefox, and doesn't happen without Pentadactyl (i.e. when searching with Ctrl+F). I'm using Mozilla Firefox 45.8.0 from Gentoo and Pentadactyl hg7290. I'm not sure how to provide more debug info since Firefox completely hangs when this happens. I provide the last 50 lines of an strace below. My session consisted of opening this page, writing "if" in the text field, and then searching for "if" with /. Firefox then hangs and I send SIGTERM to it. If the entire strace would be useful I can provide it (are there no privacy issues in doing so?).

futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
mmap(0x249d7b11a000, 65536, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x249d7b11a000
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x7f49d5bfda4c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7f49d5bfda48, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x7f49d5c00040, FUTEX_WAIT_PRIVATE, 2, NULL) = -1 EAGAIN (Resource temporarily unavailable)
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
futex(0x7f49d5c00040, FUTEX_WAKE_PRIVATE, 1) = 0
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=4565, si_uid=0} ---
unlink("/home/ff/.mozilla/firefox/32lkn570.default/lock") = 0
close(7)                                = 0
rt_sigaction(SIGTERM, {SIG_DFL, [], SA_RESTORER, 0x7f49d6d62ec0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [TERM], NULL, 8) = 0
tgkill(1920, 1920, SIGTERM)             = 0
--- SIGTERM {si_signo=SIGTERM, si_code=SI_TKILL, si_pid=1920, si_uid=1001} ---
+++ killed by SIGTERM +++
afarah1 commented 7 years ago

Okay, I was able to pinpoint the issue. It's an infinite loop in common/modules/finder.jsm:491. That is, in the highlight function of the RangeFind class. Link. When removing that loop the issue disappears entirely (though highlighting results also breaks).

I got to this by placing a breakpoint before and after the loop (after trying other spots at finder.jsm). It reaches the first breakpoint, I press play, but it never reaches the second - Firefox becomes irresponsible and I have to kill it.

I am testing it on a more recent version of Firefox than I previously reported:

:version
Pentadactyl 1.2pre (created 2017/05/31 22:07:30) running on:
Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0

Can any devs take a look at this?

Massimo-B commented 6 years ago

Any news here, if this can be fixed?

troyp commented 6 years ago

One simple way to work around this is to hide the input elements while the highlighting is done and restore them. I tested it (manually) and it works. (Obviously, the matches in the input fields are left out.)

If you restore the fields immediately after the highlighting, you do lose the wraparound behaviour of n/N however: to get back to the top match from the bottom, you have to reverse direction or repeat the search. If you leave the fields hidden, n/N wil work normally.

Note: once the fields are unhidden and the highlighting is cancelled, pressing n/N will freeze the browser, since it repeats the search highlighting with the input fields visible. (If you wanted, you could prevent this issue by never actually cancelling the search highlighting, but instead hiding it temporarily using a style.)

If you want to test it, you can use these commands from my .pentadactylrc:

command! hideselector  -nargs=* -js hideSelectors.call(null, ...args);
command! unhideselector  -nargs=* -js unhideSelectors.call(null, ...args);

js <<EOF
function hideSelectors(...sels) {
    var doc = content.document;
    sels.forEach(sel=>{
        var elts = Array.from(doc.querySelectorAll(sel));
        elts.forEach(e=>{
            var css = e.getAttribute('style') || '';
            e.setAttribute('style', css+" display: none !important;");
        });
    });
}
function unhideSelectors(...sels) {
    var doc = content.document;
    sels.forEach(sel=>{
        var elts = Array.from(doc.querySelectorAll(sel));
        elts.forEach(e=>{
            var css = e.getAttribute('style') || '';
            var hideregex = /(^|;| ) *display: *none *(!important)? *;/g;
            e.setAttribute('style', css.replace(hideregex, ''));
        });
    });
}
EOF

I tried rebinding /, n and N to hide the input fields first, and using C-/ to clear the highlighting and unhide the input fields.

map <hide-inputs> -ex hideselector input
map <unhide-inputs> -ex unhideselector input
map / <hide-inputs><find-forward>
map n <hide-inputs><find-next>
map N <hide-inputs><find-previous>
map <C-/> -ex noh | unhideselector input

but it seemed a bit unreliable, so I've settled on just rebinding / and leaving the input fields hidden. If I need them again after searching, I have a binding specifically to restore them:

map <hide-inputs> -ex hideselector input
map <unhide-inputs> -ex unhideselector input
map / <hide-inputs><find-forward>
map <C-?> <unhide-inputs>

This can be implemented in a .pentadactylrc file. A better workaround would be to hack the source so the highlight function simply ignores matches in input fields. I haven't tried that yet, but it sounds simple enough.

Massimo-B commented 6 years ago

As this issue is annoying I'm going to test your workaround. However I would appreciate a bugfix in the sources.

Massimo-B commented 6 years ago

This seems to work sometimes, but now always. For instance: Search an IP address if some edit field is open.

How to reproduce:

..freezing.

Massimo-B commented 5 years ago

This is still unstable, last freeze on https://forums.gentoo.org, writing a comment, preview, search by /, freeze. Which is most annoying as all the comment is lost...