是否可以使用GDB在pthread的线程本地存储上设置观察点?我有一个运行的程序:
equals()
...并且在几千次调用之后它返回0而不是有效指针。我真的很想弄清楚将该值设置为0.我已尝试在struct stored_type *res = pthread_getspecific(tls_key);
和pthread_setspecific
上设置断点(我能想到的唯一的事情是会合理地导致关键改变价值)并且这些断点没有被击中,所以我认为那里发生了某种超支。
我使用Linux x86_64和glibc 2.23。
答案 0 :(得分:1)
......我能想到的唯一可以合理地导致关键改变价值的事情
pthread_getspecific
返回NULL
的最可能原因:
pthread_setspecific
尚未被调用,pthread_getspecific
而当前线程正在被销毁(即pthread_exit
在堆栈的某个地方),pthread_getspecific
(pthread_*
个函数都不是异步信号安全的。)假设在你的情况下没有上述原因,那就是节目。
首先,我们需要一个测试用例来演示。
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_key_t key;
void *thrfn(void *p) {
int rc = pthread_setspecific(key, &p);
assert(rc == 0);
sleep(60);
rc = pthread_setspecific(key, (void*)0x112233);
assert(rc == 0);
return p;
}
int main()
{
pthread_t thr;
int rc = pthread_key_create(&key, NULL);
assert(rc == 0);
rc = pthread_create(&thr, NULL, thrfn, NULL);
assert(rc == 0);
sleep(90);
return 0;
}
gcc -g -pthread t.c
gdb -q ./a.out
(gdb) start
现在,使用调试信息编译GLIBC非常有帮助。大多数发行版提供libc-dbg
或类似的包,提供它。查看pthread_setspecific source,您可以看到在线程描述符(self
)内有一个specific_1stblock
数组,其中第一个PTHREAD_KEY_2NDLEVEL_SIZE
== 32个键槽的空间是预先分配(32个不同的密钥通常绰绰有余)。
我们传递的值将存储在self->specific_1stblock[key].data
中,而这正是您要设置观察点的位置。
在我们的示例程序中,key == 0
(因为这是第一个键)。把它们放在一起:
Starting program: /tmp/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Temporary breakpoint 1, main () at t.c:21
21 int rc = pthread_key_create(&key, NULL);
(gdb) b pthread_setspecific
Breakpoint 2 at 0x7ffff7bc9460: file pthread_setspecific.c, line 28.
(gdb) c
Continuing.
[New Thread 0x7ffff77f6700 (LWP 58683)]
[Switching to Thread 0x7ffff77f6700 (LWP 58683)]
Breakpoint 2, __GI___pthread_setspecific (key=0, value=0x7ffff77f5ef8) at pthread_setspecific.c:28
28 pthread_setspecific.c: No such file or directory.
(gdb) n
35 in pthread_setspecific.c
(gdb) n
28 in pthread_setspecific.c
(gdb) p self
$1 = (struct pthread *) 0x7ffff77f6700
(gdb) watch -l self.specific_1stblock[key].data
Hardware watchpoint 3: -location self.specific_1stblock[key].data
(gdb) c
Continuing.
Hardware watchpoint 3: -location self.specific_1stblock[key].data
Old value = (void *) 0x0
New value = (void *) 0x7ffff77f5ef8
__GI___pthread_setspecific (key=<optimized out>, value=0x7ffff77f5ef8) at pthread_setspecific.c:89
89 in pthread_setspecific.c
请注意,新值正是我们传递给pthread_setspecific
的值。
(gdb) c
Continuing.
Breakpoint 2, __GI___pthread_setspecific (key=0, value=0x112233) at pthread_setspecific.c:28
28 in pthread_setspecific.c
(gdb) c
Continuing.
Hardware watchpoint 3: -location self.specific_1stblock[key].data
Old value = (void *) 0x7ffff77f5ef8
New value = (void *) 0x112233
__GI___pthread_setspecific (key=<optimized out>, value=0x112233) at pthread_setspecific.c:89
89 in pthread_setspecific.c
这是我们的第二次pthread_setspecific
电话
(gdb) c
Continuing.
Hardware watchpoint 3: -location self.specific_1stblock[key].data
Old value = (void *) 0x112233
New value = (void *) 0x0
__nptl_deallocate_tsd () at pthread_create.c:152
152 pthread_create.c: No such file or directory.
这是线程破坏,它会释放线程描述符本身。
(gdb) c
Continuing.
[Thread 0x7ffff77f6700 (LWP 58683) exited]
[Inferior 1 (process 58677) exited normally]