记得以前刚接触多线程编程时,作为一个新手遇到的一个问题就是:我创建的子线程为什么没有跑起来?如以下最简单的一个程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
void *thread_function(void *arg);
char message[] = "THREAD_TEST";
struct test
{
int a;
int b;
int c;
};
struct test outpara;
int main()
{
int res;
pthread_t a_thread;
void *thread_result;
struct test para = {
.a = 10,
.b = 20,
.c = 30,
};
res = pthread_create(&a_thread, NULL, thread_function, (void *)¶);
if(res != 0)
{
perror("Pthread_create");
exit(EXIT_FAILURE);
}
printf("the thread has finish, return %d\n", ((struct test*)thread_result)->a);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
struct test inpara = *(struct test*)arg;
printf("thread is running, the parameter is %d, %d, %d\n", inpara.a,inpara.b, inpara.c);
sleep(300);
outpara.a = 100,
outpara.b = 200,
outpara.c = 300,
pthread_exit(&outpara);
}
执行结果却是诡异的:
大部分情况子线程就没有执行起来,偶尔会有一次子线程执行了。这是为什么呢?这是因为进程退出时,其创建的子线程都会被终止。那有没有办法让主线程退出时,子线程继续执行呢?有一个函数可以实现:pthread_exit()。
我们 man pthread_exit 可以看到:
pthread_exit 函数会终止调用线程,但在线程终止时,进程共享资源不会被释放,只有进程中的最后一个线程终止时,进程共享资源才会释放。
#include "Thread.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/syscall.h>
#include <signal.h>
namespace CurrentThread
{
__thread int tCachedTid = 0;
void cacheTid()
{
if(tCachedTid == 0)
{
printf("first time get tid\n");
tCachedTid = (int)syscall(SYS_gettid);
}
}
inline int tid()
{
if(tCachedTid == 0)
{
cacheTid();
}
return tCachedTid;
}
}
class CMyThread: public CThread
{
public:
CMyThread();
~CMyThread();
virtual void threadProc();
};
CMyThread::CMyThread(): CThread("myThread")
{
}
CMyThread::~CMyThread()
{
}
void CMyThread::threadProc()
{
int count = 5;
while(count--)
{
sleep(1);
printf("in CMyThread, threadID = %d\n", CurrentThread::tid());
}
pthread_exit(NULL);
}
int main()
{
CMyThread *myThread = new CMyThread();
myThread->createThread();
printf("exit main thread!\n");
pthread_exit(NULL);
return 0;
}
执行结果:
若是主线程调用 pthread_exit() 进行退出,则其创建的子线程会继续执行,直到整个进程终止。假如主线程用 return 或 exit() 进行退出,则整个进程就退出了,子线程可能还没来得及执行。
那如果子线程崩溃了,整个进程会结束吗? 如我在子线程里对NULL指针进行操作,这样会产生一个 SIGSEGV 信号:
#include "Thread.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/syscall.h>
#include <signal.h>
namespace CurrentThread
{
__thread int tCachedTid = 0;
void cacheTid()
{
if(tCachedTid == 0)
{
printf("first time get tid\n");
tCachedTid = (int)syscall(SYS_gettid);
}
}
inline int tid()
{
if(tCachedTid == 0)
{
cacheTid();
}
return tCachedTid;
}
}
class CMyThread: public CThread
{
public:
CMyThread();
~CMyThread();
virtual void threadProc();
};
CMyThread::CMyThread(): CThread("myThread")
{
}
CMyThread::~CMyThread()
{
}
void CMyThread::threadProc()
{
int count = 5;
while(count--)
{
sleep(1);
printf("in CMyThread, threadID = %d\n", CurrentThread::tid());
}
char *p = NULL;
memcpy(p, "test", 4);
pthread_exit(NULL);
}
int main()
{
CMyThread *myThread = new CMyThread();
myThread->createThread();
sleep(10);
printf("exit main thread!\n");
return 0;
}
可以看到进程结束了,没跑用例前我以为子线程崩溃主线程不会有影响,但是错误的。因为这里涉及到了信号的处理行为,子线程产生的信号应该也算是此进程产生的信号,那信号对应的处理方式是什么呢?这里找到 kernel 相关头文件里有说明 signal.h