【问题标题】:Can Thread Local Storage be faked/hacked?线程本地存储可以被伪造/黑客攻击吗?
【发布时间】:2011-10-27 19:54:41
【问题描述】:

我发现自己有点进退两难。

我有一个带有 Google 的 V8 javascript 引擎的大型应用程序。在 UI 线程上对 V8 引擎进行了一些调用。为了像大家推荐的那样对用户好,一些长操作在单独的线程上运行,而不挂起 UI 线程。但是,这些长时间运行的操作也会调用 V8 javascript 引擎。所以多线程调用 V8。

问题是,V8 似乎使用线程本地存储。这似乎使我的应用程序随机爆炸。它绝对属于“这可能是如何工作到现在?”的类。错误。

在不对我的应用程序进行重大重新架构的情况下,我提出了一个丑陋、丑陋可怕的超级黑客:我可以让 V8 认为它在不同的线程上运行吗?

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

可以吗?它会起作用吗?考虑这种卑鄙的黑客行为,我是不是很愚蠢?

【问题讨论】:

  • 为什么线程本地存储会让你的应用程序随机崩溃?知道这可能有助于解决问题而无需 hack。
  • 在尝试解决问题之前,您需要明确诊断。
  • 对 V8 的调用是什么样的?如果 V8 不能正确处理从多个线程使用的问题,那么您所做的就是将容易诊断的错误换成更微妙、不可预测和难以调试的错误。您应该真正考虑一下序列化 V8 调用的方法

标签: c++ multithreading visual-studio-2010 winapi v8


【解决方案1】:

你不应该欺骗任何东西。相反,您应该告诉 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

【讨论】:

  • 谢谢,这是一个更好的解决方案。我走得太远了!
【解决方案2】:

我遇到了同样的问题,并设法部分通过这个线程找到了解决方案。为了详细说明 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()) {}
};

【讨论】:

    猜你喜欢
    • 2011-03-05
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多