2011-10-28 54 views
1

好吧,這是我想要實現的。我希望threadRoutine分叉進程的線程只從特定點開始執行,如註釋//分支進程的線程應從此處開始執行。我使用相同的內存區域來存放原始和分叉的threadRoutine。但我懷疑,既然派生進程的threadRoutine確實執行longjmp的我設置cp_thread 1,它的棧開始從原工藝的threadRoutine了分歧,所以它不能跳,我打算。longjmp從分叉進程

我如何才能解決這個問題,那就是不偏離原來的堆棧和分叉過程threadRoutinelongjmp的的precence的派生進程。

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <setjmp.h> 

pthread_attr_t attr; 
int cp_thread = 0; 
static jmp_buf buf; 
pthread_barrier_t bar; 

void make_jmp_if_req() 
{ 
    if (cp_thread) 
     longjmp(buf, 1); 
} 

void *threadRoutine(void *threadMsg) 
{ 
    size_t myStackSize; 
    void *stackAddr; 

    make_jmp_if_req(); 

    printf("%d: TR:{stackAddr pointer = %lx, @threadRoutine = %lx}\n", 
      getpid(), stackAddr, threadRoutine); 
    pthread_attr_getstack(&attr,&stackAddr,&myStackSize); 

    setjmp(buf); 
    pthread_barrier_wait(&bar); 

    printf("%d: TR:stack address %p\n", getpid(), stackAddr); 
    printf("%d: TR:stack size is %x\n", getpid(), myStackSize); 
    //printf("%d\n",*((int *)stackAddr)); // <--------------------Causing segmentation fault.. 
    pthread_exit(NULL); 
} 

int main(int argc, char *argv[]) 
{ 
    size_t stacksize; 
    void *stackAddr; 
    int rc; 
    size_t i; 
    pthread_t thread; 
    pid_t pid; 

    pthread_attr_init(&attr); 
    // So that setjmp in the threadRoutine of the orignal process is called before    
    // longjmp from threadRoutine of the forked process. 
    pthread_barrier_init(&bar, NULL, 2); 

    stacksize = 0xC00000; //12582912; 
    stackAddr = malloc(stacksize); 
    printf("Main:{stackAddr = %lx}\n", stackAddr); 
    pthread_attr_setstack(&attr,stackAddr, stacksize); 
    pthread_attr_getstack(&attr,&stackAddr, &stacksize); 
    printf("Main:stack address %p\n",stackAddr); 
    printf("Main:stack size is %x\n",stacksize); 

    rc = pthread_create(&thread, &attr, threadRoutine, (void*)0); 
    pthread_barrier_wait(&bar); 

    switch(pid = fork()) 
    { 
    case -1: 
     printf("fork failed"); 
     break; 
    case 0: // Child 
     printf("Child pid() = %d\n", getpid()); 
     cp_thread = 1; 
     rc = pthread_create(&thread, &attr, threadRoutine,(void *)0); 
     break; 
    default:// Leader 
     printf("Parent pid() = %d\n", getpid()); 
     //rc = pthread_create(&thread, &attr, threadRoutine,(void *)0); 
    } 

    if(rc) 
    { 
     printf("ERROR:return code from pthread_create %d\n",rc); 
     exit(-1); 
    } 
    pthread_exit(NULL); 
} 
+1

當你說:「所以,請不要說不使用這個,做不同的事情,」你要求人們不回答你的問題。如果你想得到一個有用的答案,告訴我們你真的想要做什麼而不是展示「練習」。 – larsks

回答

1

我認爲你的問題是關係到一個事實,即fork()不會重現線程(現有中調用fork父進程)的子進程。在fork()之後,子進程中只存在一個線程。

此外,您應該始終在longjmp之前撥打setjmp,以便您的threadRoutine不正確。當然,你不應該把longjmp轉換成另一個線程。

請勿使用的線程無巨大的預防措施。瞭解更多關於pthread_atfork

我不明白你爲什麼要這麼做。我仍然相信你不應該這樣寫代碼(或者你不足以解釋你爲什麼要這樣做,以及爲什麼)。

問候。

+0

是的,我知道,這就是爲什麼我正在做這個練習。看看是否有可能在分叉進程中重新生成死線程。你說得對,setjmp不應該在longjmp之前被調用,也許我應該在第一個pthread_create之後並且在從原始線程執行setjmp之後放置一個障礙。我在這裏要做的是對原始線程和分叉進程和CPU狀態使用相同的堆棧,我試圖用setjmp/longjmp保存這個堆棧。 – MetallicPriest

+0

現在已經放過障礙了,所以原始進程的threadRoutine的setjmp在fork之前的threadRoutine之前調用longjmp之前。 – MetallicPriest

+0

使用此機制復活線程完全未定義。 setjmp/longjmp僅在同一個線程中使用,並且沒有保存足夠的狀態以供跨線程使用。如果您嘗試重新創建分支後的子進程中的父進程中運行的線程,那麼您應該使用協程來設計它,在分叉之前強制所有線程「加入」,然後從已知的子進程中的狀態。通常試圖在不支持它的操作系統上爲多線程進程實現forkall類似於進程掛起/恢復 – Petesh