Changeset 14893 in webkit
- Timestamp:
- Jun 16, 2006 4:47:20 PM (18 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r14883 r14893 1 2006-06-17 Anders Carlsson <acarlsson@apple.com> 2 3 Reviewed by Maciej and Geoff. 4 5 http://bugzilla.opendarwin.org/show_bug.cgi?id=7080 6 Provide some way to stop a JavaScript infinite loop 7 8 * kjs/completion.h: 9 (KJS::): 10 Add Interrupted completion type. 11 12 * kjs/function.cpp: 13 (KJS::FunctionImp::callAsFunction): 14 (KJS::GlobalFuncImp::callAsFunction): 15 Only set the exception on the new ExecState if the current one has had one. 16 17 * kjs/interpreter.cpp: 18 (KJS::TimeoutChecker::startTimeoutCheck): 19 (KJS::TimeoutChecker::stopTimeoutCheck): 20 (KJS::TimeoutChecker::alarmHandler): 21 (KJS::TimeoutChecker::pauseTimeoutCheck): 22 (KJS::TimeoutChecker::resumeTimeoutCheck): 23 New TimeoutChecker class which handles setting Interpreter::m_timedOut flag after a given 24 period of time. This currently only works on Unix platforms where setitimer and signals are used. 25 26 (KJS::Interpreter::Interpreter): 27 Initialize new member variables. 28 29 (KJS::Interpreter::~Interpreter): 30 Destroy the timeout checker. 31 32 (KJS::Interpreter::startTimeoutCheck): 33 (KJS::Interpreter::stopTimeoutCheck): 34 (KJS::Interpreter::pauseTimeoutCheck): 35 (KJS::Interpreter::resumeTimeoutCheck): 36 Call the timeout checker. 37 38 (KJS::Interpreter::handleTimeout): 39 Called on timeout. Resets the m_timedOut flag and calls shouldInterruptScript. 40 41 * kjs/interpreter.h: 42 (KJS::Interpreter::setTimeoutTime): 43 New function for setting the timeout time. 44 45 (KJS::Interpreter::shouldInterruptScript): 46 New function. The idea is that this should be overridden by subclasses in order to for example 47 pop up a dialog asking the user if the script should be interrupted. 48 49 (KJS::Interpreter::checkTimeout): 50 New function which checks the m_timedOut flag and calls handleTimeout if it's set. 51 52 * kjs/nodes.cpp: 53 (DoWhileNode::execute): 54 (WhileNode::execute): 55 (ForNode::execute): 56 Call Interpreter::checkTimeout after each iteration of the loop. 57 1 58 2006-06-15 Timothy Hatcher <timothy@apple.com> 2 59 -
trunk/JavaScriptCore/kjs/completion.h
r12317 r14893 34 34 * Completion types. 35 35 */ 36 enum ComplType { Normal, Break, Continue, ReturnValue, Throw };36 enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted }; 37 37 38 38 /** -
trunk/JavaScriptCore/kjs/function.cpp
r14834 r14893 75 75 codeType(), exec->context(), this, &args); 76 76 ExecState newExec(exec->dynamicInterpreter(), &ctx); 77 newExec.setException(exec->exception()); // could be null 77 if (exec->hadException()) 78 newExec.setException(exec->exception()); 78 79 79 80 // assign user supplied arguments to parameters … … 809 810 810 811 ExecState newExec(exec->dynamicInterpreter(), &ctx); 811 newExec.setException(exec->exception()); // could be null 812 if (exec->hadException()) 813 newExec.setException(exec->exception()); 812 814 813 815 // execute the code -
trunk/JavaScriptCore/kjs/interpreter.cpp
r14834 r14893 51 51 #endif 52 52 53 #if HAVE(SYS_TIME_H) 54 #include <sys/time.h> 55 #endif 56 53 57 #include <assert.h> 54 58 #include <math.h> … … 57 61 namespace KJS { 58 62 63 class TimeoutChecker { 64 public: 65 void startTimeoutCheck(Interpreter*); 66 void stopTimeoutCheck(Interpreter*); 67 void pauseTimeoutCheck(Interpreter*); 68 void resumeTimeoutCheck(Interpreter*); 69 70 private: 71 #if HAVE(SYS_TIME_H) 72 static Interpreter* s_executingInterpreter; 73 static void alarmHandler(int); 74 75 Interpreter* m_oldInterpreter; 76 itimerval m_oldtv; 77 itimerval m_pausetv; 78 void (*m_oldAlarmHandler)(int); 79 #endif 80 }; 81 82 #if HAVE(SYS_TIME_H) 83 Interpreter* TimeoutChecker::s_executingInterpreter = 0; 84 #endif 85 86 void TimeoutChecker::startTimeoutCheck(Interpreter *interpreter) 87 { 88 if (!interpreter->m_timeoutTime) 89 return; 90 91 interpreter->m_startTimeoutCheckCount++; 92 93 #if HAVE(SYS_TIME_H) 94 if (s_executingInterpreter == interpreter) 95 return; 96 97 // Block signals 98 m_oldAlarmHandler = signal(SIGALRM, SIG_IGN); 99 100 m_oldInterpreter = s_executingInterpreter; 101 s_executingInterpreter = interpreter; 102 103 itimerval tv = { 104 { interpreter->m_timeoutTime / 1000, (interpreter->m_timeoutTime % 1000) * 1000 }, 105 { interpreter->m_timeoutTime / 1000, (interpreter->m_timeoutTime % 1000) * 1000 } 106 }; 107 setitimer(ITIMER_REAL, &tv, &m_oldtv); 108 109 // Unblock signals 110 signal(SIGALRM, alarmHandler); 111 #endif 112 } 113 114 void TimeoutChecker::stopTimeoutCheck(Interpreter* interpreter) 115 { 116 if (!interpreter->m_timeoutTime) 117 return; 118 119 ASSERT(interpreter->m_startTimeoutCheckCount > 0); 120 121 interpreter->m_startTimeoutCheckCount--; 122 123 if (interpreter->m_startTimeoutCheckCount != 0) 124 return; 125 126 #if HAVE(SYS_TIME_H) 127 signal(SIGALRM, SIG_IGN); 128 129 s_executingInterpreter = m_oldInterpreter; 130 131 setitimer(ITIMER_REAL, &m_oldtv, 0L); 132 signal(SIGALRM, m_oldAlarmHandler); 133 #endif 134 } 135 136 #if HAVE(SYS_TIME_H) 137 void TimeoutChecker::alarmHandler(int) 138 { 139 s_executingInterpreter->m_timedOut = true; 140 } 141 #endif 142 143 void TimeoutChecker::pauseTimeoutCheck(Interpreter* interpreter) 144 { 145 ASSERT(interpreter == s_executingInterpreter); 146 147 #if HAVE(SYS_TIME_H) 148 void (*currentSignalHandler)(int); 149 150 // Block signal 151 currentSignalHandler = signal(SIGALRM, SIG_IGN); 152 153 if (currentSignalHandler != alarmHandler) { 154 signal(SIGALRM, currentSignalHandler); 155 return; 156 } 157 158 setitimer(ITIMER_REAL, &m_pausetv, 0L); 159 #endif 160 161 interpreter->m_pauseTimeoutCheckCount++; 162 } 163 164 void TimeoutChecker::resumeTimeoutCheck(Interpreter* interpreter) 165 { 166 ASSERT(interpreter == s_executingInterpreter); 167 168 interpreter->m_pauseTimeoutCheckCount--; 169 170 if (interpreter->m_pauseTimeoutCheckCount != 0) 171 return; 172 173 #if HAVE(SYS_TIME_H) 174 void (*currentSignalHandler)(int); 175 176 // Check so we have the right handler 177 currentSignalHandler = signal(SIGALRM, SIG_IGN); 178 179 if (currentSignalHandler != SIG_IGN) { 180 signal(SIGALRM, currentSignalHandler); 181 return; 182 } 183 184 setitimer(ITIMER_REAL, 0L, &m_pausetv); 185 186 // Unblock signal 187 currentSignalHandler = signal(SIGALRM, SIG_IGN); 188 #endif 189 } 190 59 191 Interpreter* Interpreter::s_hook = 0; 60 192 … … 67 199 68 200 Interpreter::Interpreter(JSObject* globalObject) 69 : m_globalExec(this, 0) 201 : m_timeoutTime(0) 202 , m_globalExec(this, 0) 70 203 , m_globalObject(globalObject) 71 204 , m_argumentsPropertyName(&argumentsPropertyName) 72 205 , m_specialPrototypePropertyName(&specialPrototypePropertyName) 206 , m_timeoutChecker(0) 207 , m_timedOut(false) 208 , m_startTimeoutCheckCount(0) 209 , m_pauseTimeoutCheckCount(0) 73 210 { 74 211 init(); … … 76 213 77 214 Interpreter::Interpreter() 78 : m_globalExec(this, 0) 215 : m_timeoutTime(0) 216 , m_globalExec(this, 0) 79 217 , m_globalObject(new JSObject()) 80 218 , m_argumentsPropertyName(&argumentsPropertyName) 81 219 , m_specialPrototypePropertyName(&specialPrototypePropertyName) 220 , m_timeoutChecker(0) 221 , m_timedOut(false) 222 , m_startTimeoutCheckCount(0) 223 , m_pauseTimeoutCheckCount(0) 82 224 { 83 225 init(); … … 111 253 { 112 254 JSLock lock; 255 256 ASSERT (m_startTimeoutCheckCount == 0); 257 ASSERT (m_pauseTimeoutCheckCount == 0); 258 259 delete m_timeoutChecker; 113 260 114 261 if (m_debugger) … … 621 768 } 622 769 770 void Interpreter::startTimeoutCheck() 771 { 772 if (!m_timeoutChecker) 773 m_timeoutChecker = new TimeoutChecker; 774 775 m_timeoutChecker->startTimeoutCheck(this); 776 } 777 778 void Interpreter::stopTimeoutCheck() 779 { 780 ASSERT(m_timeoutChecker); 781 782 m_timeoutChecker->stopTimeoutCheck(this); 783 } 784 785 void Interpreter::pauseTimeoutCheck() 786 { 787 ASSERT(m_timeoutChecker); 788 789 m_timeoutChecker->pauseTimeoutCheck(this); 790 } 791 792 void Interpreter::resumeTimeoutCheck() 793 { 794 ASSERT(m_timeoutChecker); 795 796 m_timeoutChecker->resumeTimeoutCheck(this); 797 } 798 799 bool Interpreter::handleTimeout() 800 { 801 m_timedOut = false; 802 803 return shouldInterruptScript(); 804 } 805 806 623 807 SavedBuiltins::SavedBuiltins() : 624 808 _internal(0) -
trunk/JavaScriptCore/kjs/interpreter.h
r14834 r14893 37 37 class SavedBuiltins; 38 38 class ScopeChain; 39 39 class TimeoutChecker; 40 40 41 namespace Bindings { 41 42 class RootObject; … … 50 51 class Interpreter { 51 52 friend class Collector; 53 friend class TimeoutChecker; 52 54 public: 53 55 /** … … 323 325 324 326 static Interpreter* interpreterWithGlobalObject(JSObject*); 327 328 void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; } 329 330 void startTimeoutCheck(); 331 void stopTimeoutCheck(); 332 333 void pauseTimeoutCheck(); 334 void resumeTimeoutCheck(); 335 336 bool checkTimeout(); 337 338 protected: 339 virtual bool shouldInterruptScript() { return true; } 340 long m_timeoutTime; 341 325 342 private: 343 bool handleTimeout(); 326 344 void init(); 327 345 … … 355 373 Context* m_context; 356 374 CompatMode m_compatMode; 375 376 TimeoutChecker* m_timeoutChecker; 377 bool m_timedOut; 378 379 unsigned m_startTimeoutCheckCount; 380 unsigned m_pauseTimeoutCheckCount; 357 381 358 382 ProtectedPtr<JSObject> m_Object; … … 391 415 }; 392 416 417 inline bool Interpreter::checkTimeout() 418 { 419 if (!m_timedOut) 420 return false; 421 422 return handleTimeout(); 423 } 424 393 425 } // namespace 394 426 -
trunk/JavaScriptCore/kjs/nodes.cpp
r14834 r14893 1713 1713 c = statement->execute(exec); 1714 1714 exec->context()->popIteration(); 1715 1716 if (exec->dynamicInterpreter()->checkTimeout()) 1717 return Completion(Interrupted); 1718 1715 1719 if (!((c.complType() == Continue) && ls.contains(c.target()))) { 1716 1720 if ((c.complType() == Break) && ls.contains(c.target())) … … 1757 1761 c = statement->execute(exec); 1758 1762 exec->context()->popIteration(); 1763 1764 if (exec->dynamicInterpreter()->checkTimeout()) 1765 return Completion(Interrupted); 1766 1759 1767 if (c.isValueCompletion()) 1760 1768 value = c.value(); … … 1808 1816 return c; 1809 1817 } 1818 1819 if (exec->dynamicInterpreter()->checkTimeout()) 1820 return Completion(Interrupted); 1821 1810 1822 if (expr3) { 1811 1823 v = expr3->evaluate(exec);
Note: See TracChangeset
for help on using the changeset viewer.