【问题标题】:Linux Clone "kills" main threadLinux 克隆“杀死”主线程
【发布时间】:2017-06-18 22:51:15
【问题描述】:

我正在尝试在 Linux 上用 C 语言实现线程(显然是使用 clone()),但我遇到了一个奇怪的问题。

首先,这是我的互斥函数:

void mutex_lock(int* lock) {
  while (!__sync_bool_compare_and_swap(lock, 0, 1)) {
    syscall(SYS_futex, lock, FUTEX_WAIT_PRIVATE, 1, NULL, NULL, 0);
  }
}

void mutex_unlock(int* lock) {
  if (__sync_bool_compare_and_swap(lock, 1, 0)) {
    syscall(SYS_futex, lock, FUTEX_WAKE_PRIVATE, 0, NULL, NULL, 0);
  }
}

还有我的线程结构

typedef int (*ThreadCallback)(void*);

typedef struct Thread {

  void* alloc;

  char lockSpace[sizeof(int) * 2]; /* Used to align lock pointer properly */
  int* lock;
  int started;
  int tid;

  void* stack;
  size_t stackSize;

  ThreadCallback fn;
  void* args;

}* Thread;

在我的代码中,我分配并初始化了一个稍后将使用的 Thread 结构

void* start = memAllocThread(sizeof(void*) + sizeof(struct Thread) + TH_STACK_SIZE);
if (start == NULL) {
  return TH_MEM;
}

struct Thread* th = start + TH_STACK_SIZE + sizeof(void*);
th->alloc = start;

size_t lockSpacePtr = (size_t)(th->lockSpace);
lockSpacePtr += 4 - ((lockSpacePtr % 4) % 4); /* To align ptr on? at? 4 bytes */

th->lock = (int*)lockSpacePtr;
*th->lock = 0;
th->started = 0;

th->stack = start + TH_STACK_SIZE;
th->stackSize = TH_STACK_SIZE;

th->fn = fn;
th->args = args;

其中“TH_STACK_SIZE”、“fn”和“args”分别是“0x7fff”、“ThreadCallback”和“void*”

现在我已经初始化了我的 Thread 结构,我用一个输入通道和零个输出通道初始化了 PortAudio 和默认流。然后我开始我的线程

THResult thStart(struct Thread* th) {

  int tid;

  mutex_lock(th->lock);

  if (th->started) {
    mutex_unlock(th->lock);
    return TH_RUNNING;
  }

  tid = clone(_thFunction, th->stack, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_IO | CLONE_SIGHAND | CLONE_THREAD, th);

  if (tid < 0) {
    mutex_unlock(th->lock);
    return TH_CLONE_ERRNO;
  }

  th->started = 1;
  th->tid = tid;

  mutex_unlock(th->lock);
  return TH_OK;
}

“int _thFunction(void*)”目前为空(填充时应该以th->fn开头,但这里没有问题)

现在,在调用 Pa_StartStream() 之后,我可以编写任何我想要的东西,它不会被执行(顺便说一下,如果我在代码中传播一些内容,printf 就会变得疯狂)。

  • 尝试追踪细分违规行为
  • 我删除了 Pa_StartStream :它有效,但 printf 仍然太狂野
  • 我删除了线程的开头,一切都很好

有什么想法吗?

编辑 1:

  • 当创建的线程结束时,程序结束
  • gdb 对此一无所知,我尝试通过故障分析堆栈,但没有任何问题

【问题讨论】:

  • printf(以及许多其他库函数)期望调用者是pthread 线程,而不是clone 在某些ad hoc中创建的低级任务> 方式。

标签: c linux multithreading clone portaudio


【解决方案1】:

在细分问题时,有两件事很突出。

1) 尝试从临时克隆调用 printf。很可能有标准库垃圾。

2) 仅提供 4k 堆栈。

printf(...) 替换为write(2, ...) 调用,看看是否有更好的行为。您仍然会感到头疼,但它不会立即从您的身体中消失。

或者试试gdb

exit() 退出所有线程。也许您需要以其他方式退出。从生成的线程函数返回是个坏主意,因为这会占用主线程的堆栈。

【讨论】:

  • 我添加了“EDIT 1”以带来更多细节。我还从我的线程中删除了printf's,但它仍然是一样的。但是我没有提供4k堆栈,实际上是0x7fff = 32767B。
【解决方案2】:

我大概知道为什么它不起作用了。

我了解到errno 是如何线程安全的,我认为这是因为pthreads 创建线程局部变量(由 (g)libc 使用)我的实现没有。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-16
    • 1970-01-01
    • 2011-04-19
    相关资源
    最近更新 更多