Events possibly still running async after code has been removed (stop/reload)
Reported by kolton
Suggested method of reproduction:
Slam some event with messages (say sendCopyData every 10ms from another window)
Reload script with an event of that type.
Outcome reported:
Some error, strange, doesn't give file/line no.
Suggested method of reproduction:
Slam some event with messages (say sendCopyData every 10ms from another window)
Reload script with an event of that type.
Outcome reported:
Some error, strange, doesn't give file/line no.
Leave a comment
Confirmed, attaching code to reproduce. Load same scripts in both windows, in one window run scriptBroadcast("bomb:otherWindowName"). Appears to crash every time.
file:c9L3Uw9j0r4AFEacwqjQYw
Code that gets bugged up.
Code that gets bugged up.
file:c9P9sc9j0r4AFEacwqjQYw
Main thread, starts listenerThread, kills it at appropriate time, bombs the window.
Main thread, starts listenerThread, kills it at appropriate time, bombs the window.
on 2012-09-02 19:22 *
By CrazyCasta
More accurately, the problem is that we're killing SpiderMonkey threads. Upon further examination, that is a big no-no. The proper way to do this is to get some sort of callback. In 1.7 this would be the JSBranchCallback which is triggered whenever the script branches backwards (loops basically), returns or ends. It gets called a lot so w/e gets called needs to be super simple/fast.
The solution seems simple at first, simply set the branch callback function have it call the IsAborted() function and check the result. All very simple since IsAborted() just returns a variable in the class. However, the branch callback will only be called when the JavaScript branches backward. This means that all C functions exposed (directly or indirectly) to JS need to be either: a. very fast (like unit.x, unit.name, etc.) or b. interruptable. The first most obvious case of an uninterruptable case is the delay function and any other function that calls Sleep. These need to be modified to call WaitForObject with some object that will allow interruption. Furthermore, functions like getPath that can take quite a while to return based on how they're called need to do something like ask for a branch callback while executing. This shouldn't be done every time through the innermost for loop, but a good rule of thumb would be every 1ms or so.
The solution seems simple at first, simply set the branch callback function have it call the IsAborted() function and check the result. All very simple since IsAborted() just returns a variable in the class. However, the branch callback will only be called when the JavaScript branches backward. This means that all C functions exposed (directly or indirectly) to JS need to be either: a. very fast (like unit.x, unit.name, etc.) or b. interruptable. The first most obvious case of an uninterruptable case is the delay function and any other function that calls Sleep. These need to be modified to call WaitForObject with some object that will allow interruption. Furthermore, functions like getPath that can take quite a while to return based on how they're called need to do something like ask for a branch callback while executing. This shouldn't be done every time through the innermost for loop, but a good rule of thumb would be every 1ms or so.