longjmp шиеленіскен процестен

Міне, мен қол жеткізгім келеді. Мен threadRoutine тармағындағы үрдістің тек
түсіндірмесінде көрсетілгендей, нақты нүктеден орындауды бастағанын қалаймын. threadRoutine файлының түпнұсқалық стакасы үшін бірдей жады аумағын қолданамын. Бірақ cp_thread параметрін 1-ге орнатқанымда, фортклуландырылған үдірістің threadRoutine командасы longjmp орындағанда, оның стекі < күшті> threadRoutine
және түпнұсқалық процестің өтуі мүмкін емес, сондықтан ол маған келеді.

Бұл мәселені қалай шешуге болады, бұл түпнұсқалық және threadRoutine бумаларының бөлінбейтін үдерісі үшін 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() еншілес процесте (ата-аналық процесінде бар) ойнатпайтынына байланысты. Шанышқымен() кейін бала процесінде тек бір ғана жіп бар.

Сондай-ақ, әрқашан longjmp алдында setjmp деп шақырыңыз, сондықтан сіздің threadRoutine дұрыс емес. Және, әрине, longjmp басқа басқа жіпте болмауы керек.

Ең үлкен сақтық шаралары жоқ fork арқылы жіптерді пайдаланбаңыз. pthread_atfork туралы қосымша ақпарат алыңыз.

Мен мұның бәрін не үшін істегіңіз келетінін түсінбеймін. Мен әлі күнге дейін бұл кодты жасамау керек деп ойлаймын (немесе сіз мұны не үшін қажет екенін түсіндіруге жеткіліксіз және не үшін).

Құрметпен.

1
қосылды
Иә, білемін, сондықтан мен бұл жаттығуды жасаймын. Оның өлі жіптерді ширатылған процесте қайта тірілту мүмкін екенін көру. Сіз дұрыс, setjmp longjmp алдында қоңырау шалмауы керек, мүмкін бірінші pthread_create кейін кедергіні қоюға және setjmp түпнұсқадан жасағаннан кейін. Мен мұнда жасауға тырысамын - түпнұсқалық жіпке, сондай-ақ фракция процесінде және процессордың күйінде бірдей стек болуы, мен setjmp/longjmp-пен үнемдеуге тырысамын.
қосылды автор MetallicPriest, көзі
Енді кедергілерді қойыңыз, сондықтан түпнұсқалық процедураның setjmp түпнұсқалық процесінің longymp алдында шақырылған процессдің threadRoutine деп аталады.
қосылды автор MetallicPriest, көзі
Петеш, иә, дәл осы тырысты. Айтыңызшы, егер менде 4 жіп бар болса, мен не істегім келеді, кедергіде. Және setjmp/longjmp тіркесімі арқылы және түпнұсқа және формандалған процессдегі ағындар үшін бірдей жинақтарды қолданып, мұны істеуге тырысыңыз. Сіз оларды белгілі күйден қалпына келтіруді айттыңыз. Жақсы, бірақ қалай жасауға болады, себебі бұл ағындар вырывается процесінде. Мен не істеп жатырмын? Pthread_create-ді өлі жіппен бірдей стака аймағына қарсы шақыру. Infact, мен көрдім, бұл стек өзгеріссіз қалады. setjmp қосымша стек көрсеткіші, нұсқаулық көрсеткіші және т.б. сияқты заттарды береді.
қосылды автор MetallicPriest, көзі
Бұл тетікті қолданып жіптерді қайта құру толықтай анықталмаған. Setjmp/longjmp тек бірдей ағымда пайдалану үшін анықталған және ағындарда қолданылатын жеткілікті күйді сақтамайды. Егер ата-аналық процеске өңделіп жатқан ағындарды өңделіп болғаннан кейін қайта жасауға тырыссаңыз, онда оны барлық бөлімдерді «қосылуға» мәжбүрлеп алып, содан кейін оларды белгілі файлдардан қалпына келтіріңіз. субпроцесстегі күйі. Әдетте, ОС-да жұмыс істемейтін көпфункционалды процесс үшін форс-мажорды іске асыруға тырысамын, ол тоқтатпайды/резюмеңізді өңдейді
қосылды автор Petesh, көзі