__thread,记一次不成功的socket连接

背景:公司某产品自动更新特征库需求,创建临时线程,通过socket建链并下载更新特征库,前期这个需求是同事做的,由于方案问题,做了一部分做不下去了抛给了我
基于openstack的底层重度封装产品,不同头文件引用,暴露到产品层的也有多套socket连接(呵呵)
某某头文件里是:

#ifndef socket
#define socket xx_socket
#endif

又或是某某头文件里面写的:

int socket(int domain, int type, int protocol);

引用到不同头文件,又是截然不同的结果,网络经过封装,底层看不到需要使用的逻辑IP, <sys/socket.h>中的socket行不通,需要使用xx封装的xx_socket,经过尝试后,当调用到xx_socket后发现进程出现段错误复位,调用栈中的函数代码不可见,排查入参无异常,disass反汇编该调用函数和其他已有函数,xx_socket跳转的地址相同,排除引用错误的原因。
会看调用栈,栈顶函数getCompCSI(),获取组件CSI编码,有可能是线程级变量存储,gdb断点组件流程开线程之前,p getCompCSI(),结果返回正常,进入临时线程中继续p,引发复位,问题定位,线程级变量在新开线程没有初始化原因导致。

__thread

引用gcc.gnu.org中的介绍:

5.48 Thread-Local Storage

Thread-local storage (TLS) is a mechanism by which variables are allocated such that there is one instance of the variable per extant thread. The run-time model GCC uses to implement this originates in the IA-64 processor-specific ABI, but has since been migrated to other processors as well. It requires significant support from the linker (ld), dynamic linker (ld.so), and system libraries (libc.so and libpthread.so), so it is not available everywhere.

At the user level, the extension is visible with a new storage class keyword: __thread. For example:

     __thread int i;
     extern __thread struct state s;
     static __thread char *p;

The __thread specifier may be used alone, with the extern or static specifiers, but with no other storage class specifier. When used with extern or static, __thread must appear immediately after the other storage class specifier.

The __thread specifier may be applied to any global, file-scoped static, function-scoped static, or static data member of a class. It may not be applied to block-scoped automatic or non-static data member.

When the address-of operator is applied to a thread-local variable, it is evaluated at run-time and returns the address of the current thread’s instance of that variable. An address so obtained may be used by any thread. When a thread terminates, any pointers to thread-local variables in that thread become invalid.

No static initialization may refer to the address of a thread-local variable.

In C++, if an initializer is present for a thread-local variable, it must be a constant-expression, as defined in 5.19.2 of the ANSI/ISO C++ standard.

一个简单的用例,自己跑下它:

#include <stdio.h>
#include <pthread.h>

__thread int iTestVal = 1;

void* thread1(void *arg)
{
        printf("thread1, iTestVal = %d\n", iTestVal);
        iTestVal = 2;
        sleep(1);
        printf("thread1, after delay iTestVal = %d\n", iTestVal);
}

void* thread2(void *arg)
{
        printf("thread2, iTestVal = %d\n", iTestVal);
        sleep(1);
        printf("thread2, after delay iTestVal = %d\n", iTestVal);
}


int main()
{
        pthread_t pid1, pid2;
        pthread_create(&pid1, NULL, thread1, NULL);
        pthread_create(&pid2, NULL, thread2, NULL);
        pthread_join(pid1, NULL);
        pthread_join(pid2, NULL);

        return 0;
}

结果:

[root@TubbyFlashy-VM test]# gcc -lpthread main.c 
[root@TubbyFlashy-VM test]# ./a.out 
thread2, iTestVal = 1
thread1, iTestVal = 1
thread2, after delay iTestVal = 1
thread1, after delay iTestVal = 2

0 条评论

What is 6 + 6 ?
Please leave these two fields as-is:
不答对这道小题,是不给通过的哦

昵称

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

沙发空缺中,还不快抢~