线程本地存储可以被伪造/黑客攻击吗?
我发现自己有点进退两难。
我有一个大型应用程序,其中有 Google 的 V8 javascript 引擎。一些调用是在 UI 线程上对 V8 引擎进行的。为了像大家建议的那样对用户友好,一些长时间操作在单独的线程上运行,而不挂起 UI 线程。然而,这些长时间运行的操作也会调用 V8 JavaScript 引擎。所以多个线程调用V8。
事实是,V8 似乎使用线程本地存储。这似乎使我的应用程序随机爆炸。这绝对属于“到目前为止这怎么可能行得通?”的类别。错误。
在不显着重新架构我的应用程序的情况下,我提出了一个丑陋、丑陋、可怕的超级黑客:我能让 V8 认为它在不同的线程上运行吗?
换句话说,当我第一次调用 V8 时,我会记下该线程。然后,对于对 V8 的所有其他调用,我以某种方式欺骗线程,以便线程本地存储/任何其他与线程相关的内容都可以工作。
能做到吗?它会起作用吗?我是不是太蠢了,竟然考虑这么卑鄙的黑客?
I find myself in a bit of a quandry.
I have a large application which has Google's V8 javascript engine. Some calls are made to the V8 engine on the UI thread. To be nice to the user like everyone recommends, some long operations are run on a separate thread, without hanging the UI thread. However, these long running operations also make calls in to the V8 javascript engine. So multiple threads call in to V8.
Thing is, V8 appears to use thread local storage. This seems to be making my application randomly explode. It's definitely in the class of "How was this possibley working up till now?" bugs.
Without significantly re-architecting my application, I propose an ugly, ugly horrible super-hack: can I make V8 think it's running on a different thread?
In other words, the first time I make a call in to V8, I make a note of the thread. Then, for all other calls to V8, I somehow spoof the thread so the thread local storage/whatever else thread-dependent works.
Can it be done? Will it work? Am I stupid to even consider such a scummy hack?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你不应该欺骗任何东西。相反,您应该告诉 V8 您正在尝试从不同的线程使用它。
在 3.2 版本之前的 V8 中,唯一的方法是在从不同线程使用 V8 之前使用
v8::Locker
。它保证对 V8 的独占访问并初始化存储在 TLS 中的内部结构。有关详细信息,请参阅 http://code .google.com/p/v8/source/browse/branches/3.1/include/v8.h#3189从 3.2 版本开始,V8 有了隔离的概念。如果您没有显式创建隔离,V8 会隐式创建默认隔离以保持 API 兼容。在这种情况下,您仍然可以像旧版本一样简单地使用
v8::Locker
。如果您显式创建隔离,那么除了使用v8::Locker
获取独占访问权限之外,您还必须使用v8::Isolate::Enter
在线程中显式进入和退出它们code>/v8::Isolate::Exit
方法或v8::Isolate::Scope
。有关详细信息,请参阅 http://code.google .com/p/v8/source/browse/trunk/include/v8.h#3510在大多数情况下有效的简单答案是:在使用 V8 之前使用
v8::Locker
来自不同的线程。You should not spoof anything. Instead you should tell V8 that you are trying to use it from the different thread.
In V8 prior to the version 3.2 the only way to do that is to use
v8::Locker
before using V8 from the different thread. It guarantees both exclusive access to the V8 and initializes internal structures stored in TLS. For more details see http://code.google.com/p/v8/source/browse/branches/3.1/include/v8.h#3189Starting from the version 3.2 V8 has the concept of isolate. If you are not creating isolates explicitly, V8 implicitly creates the default isolate to keep API compatible. In this case you can still simply use
v8::Locker
as in older versions. If you are creating isolates explicitly then in addition to acquiring exclusive access withv8::Locker
you also have to enter&exit them explicitly in your threads usingv8::Isolate::Enter
/v8::Isolate::Exit
methods orv8::Isolate::Scope
. For more details see http://code.google.com/p/v8/source/browse/trunk/include/v8.h#3510So simple answer that will work in most cases is: use
v8::Locker
before using V8 from the different thread.我遇到了同样的问题,并设法通过此线程找到部分解决方案。为了详细说明 VE 的答案,默认情况下不能从多个线程使用 v8。如果你愿意,你必须使用隔离和锁。
问题是你不能半途而废,除非你完全退出并破坏你的 JS 上下文,否则你不能只使用锁。由于在大多数重要情况下情况并非如此,因此您必须一路走下去,并
创建您自己的
v8::Isolate
。您可以将其设置为全局,但是(据我了解)它不能是默认的(因为默认的已经处于输入状态)。在所有调用 v8 的函数中(并且不保证是内部函数),您必须输入隔离(使用
v8::Isolate::Scope
)并且还使用“v8::Locker”对象。
我编写了一个在公共方法中使用的小辅助对象,它看起来有点像这样:
I had the same problem and managed to find the solution partly through this thread. To elaborate on VE's answer, you can not use v8 from multiple threads by default. If you want to, you have to use isolates and locks.
The problem is that you can not go half way, you can't use locks only unless you completely exit and destruct your JS context. Since this is not the case in most non-trivial cases you have to go all the way, and
Create your own
v8::Isolate
. You can make this global, but (as I understand it) it can not be the default one (because the default one is already in the entered state).In all your functions that call v8 (and are not guaranteed to be internal) you must enter your isolate (use
v8::Isolate::Scope
) andalso use 'v8::Locker' objects.
I wrote a small helper object that I use in my public methods and it looks a bit like this: