线程本地存储可以伪造/黑客

Can Thread Local Storage be faked/hacked?

本文关键字:伪造 黑客 存储 线程      更新时间:2023-10-16

我觉得自己有点左右为难。

我有一个大的应用程序,其中有谷歌的V8 javascript引擎。在UI线程上对V8引擎进行了一些调用。像每个人建议的那样,为了对用户友好,一些长时间的操作在单独的线程上运行,而不挂起UI线程。然而,这些长时间运行的操作也会调用V8 javascript引擎。所以多个线程调用V8。

问题是,V8似乎使用线程本地存储。这似乎使我的应用程序随机爆炸。这绝对属于"这怎么可能工作到现在?"的bug。

在不显著重新构建我的应用程序的情况下,我提出了一个非常非常可怕的超级hack:我能让V8认为它在不同的线程上运行吗?

换句话说,第一次调用V8时,我记录了线程。然后,对于所有对V8的其他调用,我以某种方式欺骗线程,使线程本地存储/任何其他线程依赖的工作。

可以做到吗?它会起作用吗?我蠢到居然会考虑这么个卑鄙的黑客吗?

你不应该欺骗任何东西。相反,你应该告诉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/v8::Isolate::Exit方法或v8::Isolate::Scope在线程中显式地进入和退出隔离。详细信息请参见http://code.google.com/p/v8/source/browse/trunk/include/v8.h#3510

所以在大多数情况下工作的简单答案是:在使用不同线程的V8之前使用v8::Locker

我有同样的问题,并设法通过这个线程找到部分解决方案。为了详细说明VE的答案,默认情况下你不能在多线程中使用v8。如果您愿意,则必须使用隔离和锁。

问题是你不能半途而废,除非你完全退出并销毁你的JS上下文,否则你不能只使用锁。因为在大多数非平凡的情况下都不是这样你必须一直走下去,然后

  1. 创建自己的v8::Isolate。您可以将其设置为全局,但(据我所知)它不能是默认的(因为默认的已经处于进入状态)。

  2. 在所有调用v8的函数中(不保证是内部的),您必须输入隔离(使用v8::Isolate::Scope)和

  3. 也使用'v8::Locker'对象

我写了一个小的助手对象,在我的公共方法中使用,它看起来有点像这样:

class SessionLock {
private:
    v8::Isolate::Scope scope;
    v8::Locker lock;
public:
    SessionLock() : scope(getSessionIsolate()), lock(getSessionIsolate()) {}
};