在OS X pthreads实现(http://www.opensource.apple.com/source/Libc/Libc-825.26/pthreads/thread_setup.c?txt)中,它们在线程堆栈上提供了一个虚假的返回地址(第140行):
ts->rip = (uintptr_t) routine;
/*
** We need to simulate a 16-byte aligned stack frame as if we had
** executed a call instruction. The stack should already be aligned
** before it comes to us and we don't need to push any arguments,
** so we shouldn't need to change it.
*/
ts->rdi = (uintptr_t) thread; /* argument to function */
*--sp = 0; /* fake return address */
ts->rsp = (uintptr_t) sp; /* set stack pointer */
我不明白当线程正在执行的函数调用'ret'并从堆栈弹出返回地址时,这不会因非法指令/段错误而崩溃。任何人都可以解释这是如何预防/处理的吗?
答案 0 :(得分:3)
不看其余的代码,我只能猜测。我的直觉说,被调用的线程程序(用户提供的start_routine
参数)应该永远不会返回到调用函数。
考虑一下:如果新线程 返回,则会有两个线程在同一原始代码路径上运行。我认为实际调用的线程函数是一个调用用户提供的start_routine
的包装器。当start_routine
返回时,包装器会调用pthread_exit
。
(main thread)
v
pthread_create
v
thread_setup (sets up stack), and spawns new thread
v |
return to main thread |
|
|
v
wrapper_function
v
user-supplied start_routine
| (returns)
v
wrapper_function calls
v
pthread_exit
同样,这只是一个猜测,但重点是,新线程永远不会返回到调用pthread_create
的代码。然后,包装器的目的是确保 pthread_exit
被调用。
我必须看到他们将routine
传递给thread_setup
。