Changeset 20115 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Mar 12, 2007, 8:09:37 AM (18 years ago)
Author:
ggaren
Message:

JavaScriptCore:

Reviewed by Oliver Hunt.


Fixed <rdar://problem/4681051> Installer crashes in KJS::Collector::
markOtherThreadConservatively(KJS::Collector::Thread*) trying to install
iLife 06 using Rosetta on an Intel Machine


The problem was that our thread-specific data destructor would modify the
list of active JavaScript threads without holding the JSLock, corrupting
the list. Corruption was especially likely if one JavaScript thread exited
while another was starting up.

  • JavaScriptCore.exp:
  • kjs/JSLock.cpp: Don't conflate locking the JSLock with registering a thread, since the thread-specific data destructor needs to lock without registering a thread. Instead, treat thread registration as a part of the convenience of the JSLock object, and whittle down JSLock::lock() to just the bits that actually do the locking. (KJS::JSLock::lock): (KJS::JSLock::registerThread):
  • kjs/JSLock.h: Updated comments to mention the new behavior above, and other recent changes. (KJS::JSLock::JSLock):
  • kjs/collector.cpp: (KJS::destroyRegisteredThread): Lock here. (KJS::Collector::registerThread): To match, assert that we're locked here.

JavaScriptGlue:

Reviewed by Oliver Hunt.


Updated in light of fix for <rdar://problem/4681051> Installer crashes
in KJS::Collector::markOtherThreadConservatively(KJS::Collector::Thread*)
trying to install iLife 06 using Rosetta on an Intel Machine


  • JavaScriptGlue.cpp: (JSLockInterpreter): Ensure backwards compatibility by calling registerThread() when explicitly taking the JSLock. (This doesn't happen automatically anymore.) I doubt this actally matters, but in JavaScriptGlue territory, that kind of thinking will get you killed.

WebKitTools:

Reviewed by Oliver Hunt.


Beefed up --threaded mode in light of <rdar://problem/4681051> Installer
crashes in KJS::Collector::markOtherThreadConservatively(KJS::Collector::Thread*)
trying to install iLife 06 using Rosetta on an Intel Machine


--threaded mode now runs a bunch of different JavaScript threads, randomly
killing and respawning them. This was sufficient for reproducing the
bug on my MacBook Pro.

  • DumpRenderTree/DumpRenderTree.m: (javaScriptThreads): (runJavaScriptThread): (startJavaScriptThreads): (stopJavaScriptThreads): (dumpRenderTree):
Location:
trunk/JavaScriptCore/kjs
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/JSLock.cpp

    r20104 r20115  
    5454    }
    5555    ++JSLockCount;
    56 
    57     Collector::registerThread();
    5856}
    5957
     
    6866        pthread_mutex_unlock(&JSMutex);
    6967    }
     68}
     69
     70void JSLock::registerThread()
     71{
     72    Collector::registerThread();
    7073}
    7174
     
    101104}
    102105
     106void JSLock::registerThread()
     107{
     108}
     109
    103110JSLock::DropAllLocks::DropAllLocks()
    104111{
  • trunk/JavaScriptCore/kjs/JSLock.h

    r20104 r20115  
    3131    // To make it safe to use JavaScript on multiple threads, it is
    3232    // important to lock before doing anything that allocates a
    33     // garbage-collected object or which may affect other shared state
    34     // such as the protect count hash table. The simplest way to do
    35     // this is by having a local JSLock object for the scope
    36     // where the lock must be held. The lock is recursive so nesting
    37     // is ok.
     33    // JavaScript data structure or that interacts with shared state
     34    // such as the protect count hash table. The simplest way to lock
     35    // is to create a local JSLock object in the scope where the lock
     36    // must be held. The lock is recursive so nesting is ok. The JSLock
     37    // object also acts as a convenience short-hand for running important
     38    // initialization routines.
    3839
    3940    // To avoid deadlock, sometimes it is necessary to temporarily
     
    4849    class JSLock : Noncopyable {
    4950    public:
    50         JSLock() 
     51        JSLock()
    5152        {
    5253            lock();
     54            registerThread();
    5355        }
    5456
     
    6163        static void unlock();
    6264        static int lockCount();
     65
     66        static void registerThread();
    6367
    6468        class DropAllLocks : Noncopyable {
  • trunk/JavaScriptCore/kjs/collector.cpp

    r20019 r20115  
    237237  Collector::Thread *thread = (Collector::Thread *)data;
    238238
     239  // Can't use JSLock convenience object here because we don't want to re-register
     240  // an exiting thread.
     241  JSLock::lock();
     242 
    239243  if (registeredThreads == thread) {
    240244    registeredThreads = registeredThreads->next;
    241245  } else {
    242246    Collector::Thread *last = registeredThreads;
    243     for (Collector::Thread *t = registeredThreads->next; t != NULL; t = t->next) {
     247    Collector::Thread *t;
     248    for (t = registeredThreads->next; t != NULL; t = t->next) {
    244249      if (t == thread) {
    245250        last->next = t->next;
     
    248253      last = t;
    249254    }
    250   }
     255    ASSERT(t); // If t is NULL, we never found ourselves in the list.
     256  }
     257
     258  JSLock::unlock();
    251259
    252260  delete thread;
     
    260268void Collector::registerThread()
    261269{
     270  ASSERT(JSLock::lockCount() > 0);
     271 
    262272  pthread_once(&registeredThreadKeyOnce, initializeRegisteredThreadKey);
    263273
Note: See TracChangeset for help on using the changeset viewer.