longjmp из разветвленного процесса - PullRequest
1 голос
/ 28 октября 2011

Хорошо, вот чего я хочу достичь.Я хочу, чтобы поток threadRoutine разветвленного процесса начинал выполняться только с определенной точки, как показано в комментарии // Отсюда следует начинать выполнение потока разветвленного процесса .Я использую ту же область памяти для стека оригинала и разветвленной threadRoutine .Но я подозреваю, что, поскольку threadRoutine разветвленного процесса действительно выполняет longjmp , когда я установил cp_thread в 1, его стек начинает расходиться с threadRoutine оригинального процесса, и поэтому он не может перейти туда, где я хотел.

Как я могу решить эту проблему, то есть не расходить стеки оригинала и threadRoutine разветвленного процесса в прецессии longjmp для разветвленногопроцесс.

#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 Ответ

1 голос
/ 28 октября 2011

Я думаю, что ваша проблема связана с тем, что fork() не воспроизводит потоки (существующие в родительском процессе, который вызывает fork) в дочернем процессе. После fork () в дочернем процессе существует только один поток.

Кроме того, вы должны всегда вызывать setjmp до longjmp, чтобы ваш threadRoutine был неверным. И, конечно, вы не должны longjmp в другой поток.

Не используйте нити с fork без особых мер предосторожности. Узнать больше о pthread_atfork.

И я не очень понимаю, почему вы хотите все это делать. Я все еще считаю, что вам не следует кодировать таким образом (или вам недостаточно объяснять, почему вы хотите это делать и для чего).

Привет.

...