2016-11-20 2 views
0

Avant Sierra, je pouvais initialiser GLUT sur le processus fils après avoir forci le processus d'origine. Avec la dernière version de Sierra, cela semble avoir changé. Le programme suivant se bloque avec une erreur de segmentation. Si je déplace plutôt toutes les fonctions de saturation vers le processus parent, tout fonctionne. Pourquoi y a-t-il une différence entre l'utilisation du processus parent/enfant?Utilisation de GLUT après fork sur OSX Sierra

#include <stdlib.h> 
#include <GLUT/glut.h> 

void pass(void){ 
} 

int main(int argc, char* argv[]) { 
    pid_t childpid; 
    childpid = fork(); 
    if (childpid == 0){ 
     glutInit(&argc,argv); 
     glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 
     glutInitWindowSize(100,100); 
     glutCreateWindow("test"); 
     glutDisplayFunc(pass); 
     glGetError(); 
     glutMainLoop(); 
    }else{ 
     sleep(5); 
    } 
    exit(1); 
} 

La faute de segmentation je reçois:

Crashed Thread:  0 Dispatch queue: com.apple.main-thread 

Exception Type:  EXC_BAD_INSTRUCTION (SIGILL) 
Exception Codes:  0x0000000000000001, 0x0000000000000000 
Exception Note:  EXC_CORPSE_NOTIFY 

Termination Signal: Illegal instruction: 4 
Termination Reason: Namespace SIGNAL, Code 0x4 
Terminating Process: exc handler [0] 

Application Specific Information: 
BUG IN CLIENT OF LIBDISPATCH: _dispatch_main_queue_callback_4CF called from the wrong thread 
crashed on child side of fork pre-exec 

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 
0 libdispatch.dylib    0x00007fffe8e7bd21 _dispatch_main_queue_callback_4CF + 1291 
1 com.apple.CoreFoundation  0x00007fffd3c7bbe9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 
2 com.apple.CoreFoundation  0x00007fffd3c3d00d __CFRunLoopRun + 2205 
3 com.apple.CoreFoundation  0x00007fffd3c3c514 CFRunLoopRunSpecific + 420 
4 com.apple.Foundation   0x00007fffd57e1c9b -[NSRunLoop(NSRunLoop) limitDateForMode:] + 196 
5 com.apple.glut     0x0000000104f39e93 -[GLUTApplication run] + 321 
6 com.apple.glut     0x0000000104f46b0e glutMainLoop + 279 
7 a.out       0x0000000104f24ed9 main + 121 (main.c:18) 
8 libdyld.dylib     0x00007fffe8ea4255 start + 1 

Répondre

0

fork() ne crée pas un fil, il fourches le processus. Après avoir appelé fork, vous avez deux processus avec un contenu d'espace adresse presque identique, mais leurs espaces d'adressage sont protégés les uns des autres. La règle générale concernant fork() est, que la seule chose sensisble à faire après une fork dans le processus fils, est de remplacer l'image de processus par execve(); faire autre chose exige beaucoup de prévoyance dans la conception du programme.

Les fils sont créés différemment. Je vous suggère d'utiliser les primitives de threading réelles offertes par votre langage de programmation de choix. Cela étant dit, de nombreux systèmes d'exploitation et bibliothèques GUI veulent que les parties GUI d'un processus s'exécutent dans le thread principal, ce qui peut également être une raison de la raison. Sachez également que OpenGL et multithreading sont un peu compliqués.

+0

Désolé pour le mélange des fourches/filetages. Mais ça répond à ma question. Pourquoi puis-je utiliser uniquement GLUT dans le processus parent? – hanno

+1

@hanno: Il existe certaines mises en garde concernant l'utilisation de 'fork()'. Votre question a été fermée en double et l'explication est donnée ici. Vous voudrez peut-être aussi jeter un coup d'œil à cet article: http://www.evanjones.ca/fork-is-dangerous.html - il faut noter qu'en théorie il serait possible de sectionner correctement la fourchette () 'syscall, si (et seulement si) tout le verrouillage passe par des mécanismes qui sont conscients de l'hypothétique' fork() 'section-critique; ce n'est pas le cas pour un programme suffisamment complexe qui peut utiliser plusieurs fournisseurs de verrouillage différents. – datenwolf