Closed Bug 14462 Opened 21 years ago Closed 20 years ago

JS getter/setter callouts not foolproof or fully threadsafe


(Core :: JavaScript Engine, defect, P3, major)






(Reporter: brendan, Assigned: rogerl)



(2 files)

1.  Now that JS users can implement property getters and setters, the #ifdef
JS_THREADSAFE code in jsobj.c around SPROP_GET and SPROP_SET callouts should be
unifdef'd -- single-threaded embeddings must not crash if a luser deletes the
property being got from within its getter function.

2.  The callouts from property cache hit code in jsinterp.c have always been
done without addref'ing the JSScopeProperty.  This is thread-unsafe even without
user-defined getters and setters.

Target Milestone: M14
Target Milestone: M14 → M13
Not an M13 stopper; will do early in M14.

Target Milestone: M13 → M14
Let's try that milestone move again.

Setting all Javacript bugs to rginda QA Contact.
QA Contact: cbegle → rginda
In order, changes in the patch are:

- Rename JSSLOT_ITR_STATE to be JSSLOT_ITER_STATE (avoid cybercrud abbreviation 
as cbrcrd, no more six-char id limits!).

- Property cache tests must occur with the object's scope-lock held, to close a 
race with delete (js_DestroyProperty, always called with the property's scope 
locked).  Once the cache has been hit, and before the lock is released, the 
property's refcount must be bumped.  This requires re-acquisition of the lock 
and js_DropScopeProperty afterward.

- Reworked js_FindProperty to use a do-while loop, as cx->fp->scopeChain must be 
non-null.  This avoids a gratuitous lastobj init done to "Suppress gcc warning" 
in the old revision.

- Akin to the property cache hit cases in jsinterp.c and jsobj.c's 
js_FindProperty, code to hold and drop the scope-property by its refcount that 
was #ifdef JS_THREADSAFE must be unconditional, now that user-defined getters 
and setters may delete the property id they're getting or setting.

- Fixed overlong continuation line in jsobj.h.

Adding jband -- the most recent patch, for jsinterp.c alone (it replaces that 
file's part of the original patch), removes what seems to me to be inadequate 
thread safety of debugger hook loading, via an extra re-loading step and null 
test.  Jband, can you say what the thread hazard is there?  I think for now it's 
best to just load and use such pointers, and their hook-data arguments.

Rogerl has kindly offered to get this checked in,

Assignee: brendan → rogerl
The debugger threadsafety issue was that the debugger might be setting and 
clearing hooks on some arbitrary other thread. What I didn't want to do was 
something like:

if(rt->throwHook) {

...because rt->throwHook could become null after the test and before the call. 
That is why I added the local copy of the pointer. The rule in JSD is that if 
you clear a hook the old hook address needs to be able to handle being called 
and fail gracefully if appropriate. You've preserved that local copy of the 
pointer. Which is good.

The double test that you did remove was just a (probably misguided) attempt to 
minimize the impact of having the hook when the hook is null (the normal case). 
I just wanted to avoid the store to local unless a hook was really present. But 
it was doing a second test to deal with the case where the hook might get 
cleared between the first test and the store. 
If you are willing to incur the potential cost of a rarely necessary store 
before the test then that's fine with me. I suppose that a good optimizing 
compiler could make the store only happen if the test succeeds - because the 
local is only using inside the 'if' block.

Nevertheless, I don't see any problem with the changes you made here.
Brendan's fixes checked in.
Closed: 20 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.