当前位置: 首页 > 知识库问答 >
问题:

由迂回的pthread_create生成的线程不执行指令

卢志行
2023-03-14

我有一个在macOS上绕道的自定义实现和一个使用它的测试应用程序,它是用C编写的,为macOSx86_64编译,运行在英特尔i9处理器上。

该实现与多种功能一起工作良好。但是,如果我绕道pthread_create,我会遇到奇怪的行为:通过绕道pthread_create生成的线程不执行指令。我可以逐个逐步执行说明,但一旦我继续,它就不会进展。不涉及互斥锁或同步,函数的结果是 0(成功)。关闭绕道的完全相同的应用程序工作正常,因此不太可能成为罪魁祸首。

这不会一直发生 - 有时它们很好,但在其他时候,测试应用程序在以下状态下停滞:

(lldb) bt all
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x00007fff7296f55e libsystem_kernel.dylib`__ulock_wait + 10
    frame #1: 0x00007fff72a325c2 libsystem_pthread.dylib`_pthread_join + 347
    frame #2: 0x0000000100001186 DetoursTestApp`main + 262
    frame #3: 0x00007fff7282ccc9 libdyld.dylib`start + 1
    frame #4: 0x00007fff7282ccc9 libdyld.dylib`start + 1
  thread #2
    frame #0: 0x00007fff72a2cb7c libsystem_pthread.dylib`thread_start

相关的内存页面设置了可执行标志。拦截线程创建的迂回函数如下所示:

static int pthread_create_detour(pthread_t* thread,
                                 const pthread_attr_t* attr,
                                 void* (*start_routine)(void*),
                                 void* arg)
{
    detour_count++;
    pthread_fn original = (pthread_fn)detour_original(dlsym((void*)-1, "pthread_create"));
    return original(thread, attr, start_routine, arg);
}

其中detour_original检索指向[函数序言的原始函数大小]的指针。通过指令跟踪,一切似乎都正常工作,并且pthread_create成功终止。通过dtruss跟踪应用程序的系统调用确实显示对

bsdthread_create(0x10DB964B0, 0x0, 0x7000080DB000)               = 29646848 0

我所确认的是正确的论点。

这种行为仅在发布版本中观察到 - 调试工作正常,但在这两种情况下,反汇编和执行绕行pthread_create和关联的绕行代码似乎是相同的。

我发现了一些奇怪的解决此问题的方法,这些解决方法没有多大意义。给定绕行函数,许多内容可以替换为以下内容:

static int pthread_create_detour(pthread_t* thread,
                                 const pthread_attr_t* attr,
                                 void* (*start_routine)(void*),
                                 void* arg)
{
    detour_count++;
    pthread_fn original = (pthread_fn)detour_original(dlsym((void*)-1, "pthread_create"));
    <...> <== SUBSTITUTE HERE
    return original(thread, attr, start_routine, arg);
}
    < li >缓存刷新。
    __asm__ __volatile__("" ::: "memory");
    _mm_clflush(real_pthread_create);

所有这些似乎都指向一个陈旧的指令缓存。然而,英特尔手册声明如下:

对当前缓存在处理器中的代码段中的内存位置的写入会导致关联的缓存行(或多行)无效。此检查基于指令的物理地址。此外,P6系列和奔腾处理器检查对代码段的写入是否可以修改已预取以供执行的指令。如果写入影响预取指令,则预取队列无效。后一种检查基于指令的线性地址。

更有趣的是,这些解决方案必须为创建的每个新线程执行,执行发生在主线程上,因此不太可能是缓存。我还尝试在每次写入指令的内存写入时进行缓存刷新,但这没有帮助。我还编写了一个<code>memcpy

下一个嫌疑犯是种族状况。然而,目前还不清楚什么是赛车,因为一开始没有其他线程。我已经对随机生成的数字进行了斐波那契序列计算,这仍然会使新生成的线程停滞。

是什么导致了这个问题?还有哪些其他机制可以对此负责?

在这一点上,我已经没有东西要检查,所以任何建议都将受到欢迎。

共有1个答案

彭宏义
2023-03-14

我发现衍生线程不执行指令的原因是,由于我的detours实现的问题,在执行< code>pthread_create时,没有在正确的时间清除< code>r8寄存器。

如果我们查看函数的反汇编,它被分成两部分-在内部<code>_pthread_create

libsystem_pthread.dylib`pthread_create:
    0x7fff72a2e236 <+0>: 45 31 c0        xor    r8d, r8d
    0x7fff72a2e239 <+3>: e9 40 37 00 00  jmp    0x7fff72a3197e            ; _pthread_create

libsystem_pthread.dylib`_pthread_create:
    0x7fff72a3197e <+0>:    55                                push   rbp
    0x7fff72a3197f <+1>:    48 89 e5                          mov    rbp, rsp
    0x7fff72a31982 <+4>:    41 57                             push   r15
    <...> // the rest of the 1409 instructions

我的实现将绕过内部的< code>_pthread_create函数,而不是包含实际入口点的头,这意味着< code>r8将在错误的时间(绕过之前)被清除。因为迂回函数包含一些可能,所以执行过程类似于:

pthread_creater8被清除)-

这意味着根据< code > pthread _ create _ detour 函数的内容,< code>r8在返回内部函数时不会总是以0结束。

现在还不清楚为什么在<code>_pthread_create

 类似资料:
  • 我确信这两个列表都不是空的,并且正在调用,但是没有调用order execution run方法....

  • 我是spring batch的新手。我已经使用多个线程从spring创建并成功执行了作业,它工作得很好,只是当程序执行完成时,程序流不会结束/停止。i、 即使main方法的最后一条语句被执行,程序也不会退出。我不确定它是否一直在等待线程完成,或者是什么。有人能给我一些建议吗?“下面是我的作业配置文件 下面是启动器代码 如上所述,代码在5个不同的线程中为任务“hello”运行,为任务“world”运

  • 客户端创建新的websocket从池中取出一个线程来创建ServerEndpoint的新实例并执行@onOpen方法。在该线程放回池中之后。 客户端通过websocket向服务器发送消息。从池中取出线程以执行@onMessage方法。在该线程放回池中之后。 客户端关闭websocket-从池中取出线程以执行@onClose方法。在该线程放回池中之后。 这都意味着ServerEndpoint的每个方

  • 假设我有下面的代码,并且makePool可以被多个线程调用。我正在使用ThreadFactoryBuilder来确保线程具有唯一的名称。

  • 我在库中公开了一个方法,该方法返回一个CompletableFuture。该方法的计算发生在单线程执行器上,这是我的瓶颈,因此我不希望任何后续工作发生在同一个线程上 如果我使用返回“SupplySync”结果的简单方法,我将向调用者公开我宝贵的线程,调用者可能会添加同步操作(例如通过Accept),这可能会在该线程上花费一些CPU时间 复制如下: 这确实打印出: 我发现的一个解决方案是引入另一个执

  • 这是我的设置。cx\u冻结的py文件 可执行文件是没有错误的。但是当我尝试运行它时,我得到以下窗口: 标题:cx\U冻结:主脚本中出现Python错误 内容:回溯(最后一次调用):文件“c:\Users\Admin\AppData\Local\Programs\Python\Python35-32\lib\site packages\cx\u Freeze\initscripts\uuuuuu s