longjmp з проколів процесу

Гаразд, ось що я хочу досягти. Я хочу, щоб потока ThreadRoutine вирощуваного процесу почала виконуватися лише з певної точки, як показано в коментарях //Поточний процес вилка має розпочатися звідси . Я використовую ту саму область пам'яті для стеку оригіналу та forked threadRoutine . Але я підозрюю, що оскільки threadRoutine обробного процесу виконує longjmp , я встановлюю cp_thread до 1, його стек починає відхилятися від < strong> threadRoutine оригінального процесу, і тому він не може перейти, де я мав намір.

Як я можу вирішити цю проблему, тобто не розходяться стек оригіналу і <�сильного> threadRoutine з роздвоєного процесу в precence з <�сильного> longjmp для роздвоєного процесу.

#include 
#include 
#include 
#include 
#include 

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() у дочірньому процесі існує лише одна гілка.

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

Не використовуйте нитки за допомогою fork без величезних запобіжних заходів. Дізнайтеся більше про pthread_atfork .

І я не розумію, чому ти хочеш це все зробити. Я все ще вірю, що ви не повинні кодувати таким чином (або ви недостатньо пояснюєте, чому ви хочете це зробити, і для чого).

З повагою

1
додано
Так, я знаю, і саме тому я виконую цю вправу. Ви бачите, чи можливо його відновити мертві нитки у вигнутому процесі. Ви маєте рацію, setjmp не слід викликати до longjmp, можливо, я повинен поставити бар'єр після першого pthread_create і після того, як зробив setjmp з вихідного потоку. Сюди, що я намагаюся зробити, це мати той самий стек для вихідного потоку, а також той, що знаходиться в процесі виробу та стан центрального процесора, який я намагаюся зберегти за допомогою setjmp/longjmp.
додано Автор MetallicPriest, джерело
Тепер поставте перешкоди, так що setjmp threadRoutine оригінального процесу викликається перед longjmp від threadRoutine з вирощуваного процесу.
додано Автор MetallicPriest, джерело
Петєш, так, саме те, що я намагався. Скажіть, якщо у мене 4 потоку, я б хотів це зробити, щоб розгортати точку бар'єру. І через комбінацію setjmp/longjmp та використання тих самих стеків для потоків в оригінальному та прокручуваному процесі спробуйте це зробити. Ви сказали, щоб відновити їх у відомому штаті. Гаразд, але як я можу це зробити, так як нитки мертві в процесі. Що я робив, це викликати pthread_create проти тієї ж зони стеків, що використовується мертвою ниткою. Інфакт, я бачив, що стек залишається недоторканим. setjmp додатково дає такі речі, як покажчик стека, покажчик інструкцій тощо.
додано Автор MetallicPriest, джерело
Воскресіння ниток за допомогою цього механізму абсолютно невизначено. Setjmp/longjmp визначається лише для використання в межах одного потоку і не зберігає достатньо стану для використання в потоках. Якщо ви намагаєтесь відтворити потоки, які були запущені у батьківському процесі в підпроцесі після вилучення, тоді ви повинні спроектувати його за допомогою кортиналів, де ви заставляєте всі теми "приєднуватися" перед їх створенням, а потім відновлюєте їх з відомого стан в підпроцесі. Як правило, спроба реалізації forkall для багатопотокового процесу в ОС, яка не підтримує її, схожа на обробку призупинення/відновлення
додано Автор Petesh, джерело