在 Windows 脚本组件中使用时,VBScript 中的 RegExp 对象是否线程安全

发布于 2024-10-16 13:57:41 字数 2872 浏览 7 评论 0原文

我试图找出我们使用的旧版 Windows 脚本组件的问题。查看 WinDbg 中的几个内存转储,我发现很多线程实际上看起来 50% 的应用程序线程都在等待另一个线程完成。该线程有一个很长的堆栈,位于下面。该线程正在使用 RegExp 对象进行一些工作,所以我现在的问题是 RegExp 线程安全吗?

它看起来当然不是来自等待它的所有其他线程,但在我得出结论并努力在网上找到任何真实信息之前,我想确定一下。

vbscript!RegExpExec::PopGreedyStar+3a    
vbscript!RegExpExec::FExecAux+639    
vbscript!RegExpExec::FExec+1f    
vbscript!RegExpExec::Exec+5a0    
vbscript!RegExpExec::ReplaceUsingString+2d    
vbscript!CRegExp::OrigReplace+14e    
vbscript!CRegExp::Replace+80    
oleaut32!DispCallFunc+16a    
oleaut32!CTypeInfo2::Invoke+234    
vbscript!CRegExp::Invoke+24    
vbscript!IDispatchInvoke2+b2    
vbscript!IDispatchInvoke+59    
vbscript!InvokeDispatch+13a    
vbscript!InvokeByName+42    
vbscript!CScriptRuntime::RunNoEH+22b2    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1e02    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CSession::Execute+c8    
vbscript!NameTbl::InvokeEx+516    
scrobj!DoInvoke+2c    
scrobj!NameTable::InvokeEx+e6    
scrobj!ComDispatchEx::InvokeEx+25    
scrobj!DoInvoke+2c    
scrobj!InvokeMember+a3    
scrobj!NameTable::InvokeEx+aa    
scrobj!ComDexHandler::Inner::InvokeEx+25    
vbscript!IDispatchExInvokeEx2+a9    
vbscript!IDispatchExInvokeEx+56    
vbscript!InvokeDispatch+101    
vbscript!InvokeByName+42    
vbscript!CScriptRuntime::RunNoEH+234c    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1bbd    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CSession::Execute+c8    
vbscript!NameTbl::InvokeEx+516    
vbscript!IDispatchExInvokeEx2+a9    
vbscript!IDispatchExInvokeEx+56    
vbscript!InvokeDispatch+101    
vbscript!InvokeByName+42    
vbscript!CScriptRuntime::RunNoEH+234c    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1bbd    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1bbd    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1bbd    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CSession::Execute+c8    
vbscript!NameTbl::InvokeEx+516    
vbscript!IDispatchExInvokeEx2+a9    
vbscript!IDispatchExInvokeEx+56    
vbscript!InvokeDispatch+101    
vbscript!InvokeByName+42    
vbscript!CScriptRuntime::RunNoEH+234c    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1beb    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CSession::Execute+c8    
vbscript!COleScript::ExecutePendingScripts+144    
vbscript!COleScript::SetScriptState+14d 

I've trying to track down an issue with a legacy Windows Scripting Component that we use. Looking at several memory dumps in WinDbg I have found that alot of threads, in fact looks like 50% of the apps threads are all waiting for another thread to complete. This thread has a long stack which is below. This thread is doing some work with a RegExp object, so my question is now is RegExp thread safe?

It certainly looks like it isn't from all the other threads waiting on it but I want to be certain before I jump to conclusions and have struggled to find any real information online.

vbscript!RegExpExec::PopGreedyStar+3a    
vbscript!RegExpExec::FExecAux+639    
vbscript!RegExpExec::FExec+1f    
vbscript!RegExpExec::Exec+5a0    
vbscript!RegExpExec::ReplaceUsingString+2d    
vbscript!CRegExp::OrigReplace+14e    
vbscript!CRegExp::Replace+80    
oleaut32!DispCallFunc+16a    
oleaut32!CTypeInfo2::Invoke+234    
vbscript!CRegExp::Invoke+24    
vbscript!IDispatchInvoke2+b2    
vbscript!IDispatchInvoke+59    
vbscript!InvokeDispatch+13a    
vbscript!InvokeByName+42    
vbscript!CScriptRuntime::RunNoEH+22b2    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1e02    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CSession::Execute+c8    
vbscript!NameTbl::InvokeEx+516    
scrobj!DoInvoke+2c    
scrobj!NameTable::InvokeEx+e6    
scrobj!ComDispatchEx::InvokeEx+25    
scrobj!DoInvoke+2c    
scrobj!InvokeMember+a3    
scrobj!NameTable::InvokeEx+aa    
scrobj!ComDexHandler::Inner::InvokeEx+25    
vbscript!IDispatchExInvokeEx2+a9    
vbscript!IDispatchExInvokeEx+56    
vbscript!InvokeDispatch+101    
vbscript!InvokeByName+42    
vbscript!CScriptRuntime::RunNoEH+234c    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1bbd    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CSession::Execute+c8    
vbscript!NameTbl::InvokeEx+516    
vbscript!IDispatchExInvokeEx2+a9    
vbscript!IDispatchExInvokeEx+56    
vbscript!InvokeDispatch+101    
vbscript!InvokeByName+42    
vbscript!CScriptRuntime::RunNoEH+234c    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1bbd    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1bbd    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1bbd    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CSession::Execute+c8    
vbscript!NameTbl::InvokeEx+516    
vbscript!IDispatchExInvokeEx2+a9    
vbscript!IDispatchExInvokeEx+56    
vbscript!InvokeDispatch+101    
vbscript!InvokeByName+42    
vbscript!CScriptRuntime::RunNoEH+234c    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CScriptRuntime::RunNoEH+1beb    
vbscript!CScriptRuntime::Run+62    
vbscript!CScriptEntryPoint::Call+51    
vbscript!CSession::Execute+c8    
vbscript!COleScript::ExecutePendingScripts+144    
vbscript!COleScript::SetScriptState+14d 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

新一帅帅 2024-10-23 13:57:41

我不知道你的情况的线程安全。但是,根据您的情况,我认为这更有可能是正则表达式本身的问题。这将是我首先要考虑的事情。由于量词和重新启动,创建的正则表达式本身可能会导致堆栈溢出或非常长的运行时间。

来自 pcre 手册页

   When a pattern contains an unlimited repeat inside  a  subpattern  that
   can  itself  be  repeated  an  unlimited number of times, the use of an
   atomic group is the only way to avoid some  failing  matches  taking  a
   very long time indeed. The pattern

     (\D+|<\d+>)*[!?]

   matches  an  unlimited number of substrings that either consist of non-
   digits, or digits enclosed in <>, followed by either ! or  ?.  When  it
   matches, it runs quickly. However, if it is applied to

     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

   it  takes  a  long  time  before reporting failure. This is because the
   string can be divided between the internal \D+ repeat and the  external
   *  repeat  in  a  large  number of ways, and all have to be tried. (The
   example uses [!?] rather than a single character at  the  end,  because
   both  PCRE  and  Perl have an optimization that allows for fast failure
   when a single character is used. They remember the last single  charac-
   ter  that  is required for a match, and fail early if it is not present
   in the string.) 

现在,Windows 脚本宿主中可用的 RegExp 对象不是 pcre,但我相信同样的行为也适用于它。

因此,请检查您的正则表达式是否有嵌套的无限量词。

I don't know about thread safety in your case. But, looking at your situation, I'd say it's more likely to be a problem in the regex itself. That would be the first thing I would look at. It's possible to create a regex that itself causes a stack overflow, or a very very long runtime, because of quantifiers and re-starts.

From the pcre man page:

   When a pattern contains an unlimited repeat inside  a  subpattern  that
   can  itself  be  repeated  an  unlimited number of times, the use of an
   atomic group is the only way to avoid some  failing  matches  taking  a
   very long time indeed. The pattern

     (\D+|<\d+>)*[!?]

   matches  an  unlimited number of substrings that either consist of non-
   digits, or digits enclosed in <>, followed by either ! or  ?.  When  it
   matches, it runs quickly. However, if it is applied to

     aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

   it  takes  a  long  time  before reporting failure. This is because the
   string can be divided between the internal \D+ repeat and the  external
   *  repeat  in  a  large  number of ways, and all have to be tried. (The
   example uses [!?] rather than a single character at  the  end,  because
   both  PCRE  and  Perl have an optimization that allows for fast failure
   when a single character is used. They remember the last single  charac-
   ter  that  is required for a match, and fail early if it is not present
   in the string.) 

Now, the RegExp object available in the Windows Script Host is not pcre, but I believe the same behavior would have to apply to it.

So, check your regex for nested unlimited quantifiers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文