2010-05-03 4 views
3

J'ai un processus parent et enfant, et le parent peut lire la sortie de l'enfant et l'envoyer à l'entrée de l'enfant. Jusqu'à présent, tout fonctionne correctement avec les scripts shell, testant les commandes qui entrent et sortent les données. Je viens de tester avec un simple programme C et je n'arrivais pas à le faire fonctionner. Voici le programme C:sélectionner échouer avec le programme C mais pas le shell

#include <stdio.h> 

int main(void) { 
    char stuff[80]; 
    printf("Enter some stuff:\n"); 
    scanf("%s", stuff); 

    return 0; 
} 

Le problème avec le programme C est que mon select ne parvient pas à lire la fd des enfants et par conséquent le programme ne peut pas finir. Voici le bit qui fait la sélection ..

//wait till child is ready 
fd_set set; 
struct timeval timeout; 

FD_ZERO(&set); // initialize fd set 
FD_SET(PARENT_READ, &set); // add child in to set 
timeout.tv_sec = 3; 
timeout.tv_usec = 0; 

int r = select(FD_SETSIZE, &set, NULL, NULL, &timeout); 
if(r < 1) { // we didn't get any input 
    exit(1); 
} 

Est-ce que quelqu'un a une idée pourquoi cela se passerait-il avec le programme C et non une coquille?

Éditer: Je dois préciser que le processus fils appelle exec sur un argument, donc je n'y ai pas accès après ce point.

Répondre

2

Le problème est que le processus de mise en mémoire tampon enfant est complètement la sortie, car il est en train d'écrire à un tuyau et non un terminal. Utilisez setvbuf pour forcer la mise en mémoire tampon ou le mode sans tampon, ou ajoutez un fflush explicite à l'enfant après printf, ou utilisez le programme unbuffer fourni avec Expect pour que la bibliothèque libc considère que le programme fonctionne de manière interactive.

+0

Bon rappel re 'setvbuf'; J'espère que cela ne vous dérange pas d'incorporer la suggestion. –

+0

@Charles: Il y avait une période d'environ 5 ans quand c'était une question standard chez les nouveaux arrivants à la communauté Tcl ("pourquoi mon sous-processus ne fonctionne pas ?!") et ma réponse est la distillation de ce que nous avons dit leur. (Eh bien, utiliser la version complète d'Expect est la vraie solution que nous préférions à l'époque, mais cela ne va pas répondre à cette question.) –

+0

Le processus fils utilise exec, donc fflush() n'est pas vraiment une option. J'ai essayé d'utiliser setvbuf (stdout, (char *) NULL, _IONBF, 0); sur l'enfant avant l'exécutif, mais cela ne semblait pas fonctionner. Avez-vous une idée pourquoi? – Gary

1

Vider votre stdout avant de bloquer l'entrée dans le programme C.

fflush(stdout); 

En shell, ceci est souvent implicite.

Vous pouvez également utiliser setvbuf() pour désactiver la mise en mémoire tampon (ou activer la mise en mémoire tampon de ligne). Cela doit être appelé avant que les données sont écrites:

setvbuf(stdout, NULL, _IONBF, 0) 
Questions connexes