2011-11-16 9 views
6

Tengo algo de código que imprime en la salida estándar, en pseudo código que parececómo comprobar si una salida estándar está cerrada

int main(){ 
    //allocate data 
    while(conditional){ 
     char *string = makedata(); 
     fprintf(stdout,"%s",string); 
    } 
    //cleanup 
} 

Esto funciona bien, si el condicional se puede cambiar entre a cero, pero si la tubería del salida como

./a.out |head -n10 >dumped 

Entonces el código nunca llega a la parte de limpieza, no entiendo cómo comprobar si se cierra el stdout.

Gracias

+0

¿Qué pasa con 'feof()' y 'ferror()'? –

Respuesta

5

Su stdout no se ha cerrado, por lo que revisarlo será inútil. Su programa ha recibido un SIGPIPE y salió. Un SIGPIPE se entrega cada vez que su programa escribe en un conducto en el que no hay lectores. En su ejemplo, eso sucede cuando sale head, cerrando su stdin.

Debe ignorar SIGPIPE si desea que su programa continúe. Este código ignorará SIGPIPE:

(void)signal(SIGPIPE, SIG_IGN); 

Si no desea modificar su programa, puede organizar que algo sigue leída de la tubería, incluso después de head cierra su entrada.

./a.out | (head -n10 >dumped ; cat > /dev/null) 

: El ejemplo shell es válido para bash, quizás no para CSH.

+1

stdout está cerrado. El acto de escribir en un descriptor de archivo que se ha cerrado genera el SIGPIPE. –

+1

@WilliamPursell - No, el * otro * extremo de la tubería se ha cerrado. El acto de escribir en un descriptor de archivo de tubería o zócalo en el que se cierra el otro extremo genera un SIGPIPE. El acto de escribir en el descriptor de archivo que se ha cerrado genera EBADF. –

0

yo no he probado esto, pero con tal que estuviera usando el descriptor de archivo estándar para la salida estándar, es posible que pueda para tratar de realizar una fstat (1, & stat_structure) y comprobar los códigos de retorno y de error .

3

Se cierra al matar el proceso con SIGPIPE.

Si quieres ir cuando se hace caso omiso de su salida, a continuación, configurar un controlador SIG_IGN para SIGPIPE, y controlar el error de la fprintf (que se retrasó por el almacenamiento en búfer, por lo que no se puede asumir datos que han sido escritos ha llegado al usuario).

1

Como señala Rob en los comentarios a su respuesta, no le preocupa que se haya cerrado el stdout; más bien, te preocupa que el otro extremo de la tubería esté cerrado. Esto puede ser una pedantería, pero conduce a la solución de su problema. A saber, no le importa si stdout está cerrado, pero solo si su printf tiene éxito. Debería verificar el valor de retorno de printf: si es -1, entonces la escritura ha fallado.

Como señala Simon Richter, nunca obtendrá el valor de retorno de printf si no ignora SIGPIPE, porque el resultado de escribir en stdout cuando se cerró el otro lado de la tubería es que se enviará SIG_PIPE a el proceso. Por lo tanto, debe hacer algo como:

 
    signal(SIGPIPE, SIG_IGN); /* Careful: you now must check the return of *all* writes */ 
    if(fprintf(stdout, ...) == -1) { 
    /* handle the error */ 
    } 
Cuestiones relacionadas