2010-02-02 19 views

Respuesta

3

Esta fue una buena pregunta, aunque preguntas similares se han hecho aquí muchas veces. Estaba interesado en el aspecto OSX porque trato de ponerme al día con ese sistema. (tal vez debería agregar la etiqueta OSX)

I THINK fprintf() es seguro para subprocesos en OSX. Mi primera razón para esto es que la gente de Darwin iba en esa dirección, como lo demuestra su decisión de abandonar el 'error' global de la vieja escuela a favor de la función errno(). Para la documentación, simplemente siga '/usr/include/errno.h'. Sin eso, ninguna de las cosas de la libc sería segura. Sin embargo, el uso de la función errno() no prueba nada sobre fprintf(). Es solo un comienzo. Estoy seguro de que todos conocen al menos una situación en la que Apple no llevó a cabo una buena idea.

Otra razón por la que creo en la 'seguridad de hilos' de fprintf() es la source code, que se supone que es 'la cosa real', al menos hasta 10.6 cuando Apple cerró (parte/todo) de OSX. Escanee ese código para "MT-Safe" y verá un CLAIM que la versión no local de 'vfprintf()' es segura para subprocesos. De nuevo, eso no prueba nada. Sin embargo, es una forma de documentación que usted quería.

Mi última razón para creer que fprintf() es seguro para subprocesos era un caso de prueba. Esto tampoco prueba mucho de nada. Quizás demuestra que el espacio del búfer es seguro para subprocesos. OK, fue una excusa para escribir un pequeño programa por diversión. En realidad, no lo escribí. Encontré un esqueleto en línea y lo modifiqué. La definición "FLUSH_BUFFER" le permite ver más claramente lo que está sucediendo. Si esa macro no está definida, se obtiene una prueba de buffer 'sort-of' (el mismo texto sin algunos terminadores de línea). No pude encontrar la manera de organizar una colisión más significativa de los hilos.

Supongo que es posible que esté escribiendo en varios archivos. Escribir en un solo archivo es probablemente una mejor prueba. El programa adjunto no es una prueba definitiva. Aunque podría extenderse, no estoy seguro de que algún programa pueda ser definitivo. En pocas palabras: tal vez debería simplemente silenciar sus llamadas a fprintf().

// artificial test for thread safety of fprintf() 
// define FLUSH_BUFFER to get a good picture of what's happening, un-def for a buffer test 
// the 'pretty print' (FLUSH_BUFFER) output relies on a mono-spaced font 
// a writeable file name on the command line will send output to that file 
// 

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define FLUSH_BUFFER 

#define NTHREAD  5 
#define ITERATIONS 3 

const char DOTS[] = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "; 
FILE *outFile; 

void *PrintHello(void *threadid) { 
    long tid; 

    tid = (long)threadid; 
    for (int i=1; i<=ITERATIONS; i++) { 
     long delay = (NTHREAD-tid) * 100000 + (ITERATIONS-i+1) * 10000; 
#ifdef FLUSH_BUFFER 
     fprintf(outFile, "%*sStart thread %d iteration %d\n", (tid+1)*4, " ", tid, i); 
     usleep(delay); 
     fprintf(outFile, "%*sFinish thread %d iteration %d %*.*sw/delay %d\n", 
       (tid+1)*4, " ", tid, i, (NTHREAD-tid+1)*4, (NTHREAD-tid+1)*4, DOTS, delay); 
#else 
     fprintf(outFile, "Start thread %d iteration %d ", tid, i); 
     usleep(delay); 
     fprintf(outFile, "Finish thread %d iteration %d w/delay %d\n", tid, i, delay); 
#endif 
    } 
    pthread_exit(NULL); 
} 

int main (int argc, char *argv[]) { 
    pthread_t threads[NTHREAD]; 
    char errStr[100]; 
    int rc; 
    long t; 

    if(argc > 1) { 
     if(! (outFile = fopen(argv[1], "w"))) { 
      perror(argv[1]); 
      exit(1); 
     } 
    } else 
     outFile = stdout; 

    for(t=0; t<NTHREAD; t++) { 
     fprintf(outFile, "In main: creating thread %ld\n", t); 
     if(rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t)) { 
      sprintf(errStr, "ERROR; pthread_create() returned %d", rc); 
      perror(errStr); 
      exit(2); 
     } 
    } 
    pthread_exit(NULL); 
} 
5

El POSIX hilos especificación (AKA Pthreads), que OS X se ajusta a, requiere que las funciones stdio son seguros para subprocesos. También proporciona las funciones flockfile y funlockfile para garantizar que otros hilos no puedan intercalar E/S en un ARCHIVO * mientras esté bloqueado.

Consulte http://pubs.opengroup.org/onlinepubs/007908799/xsh/threads.html, específicamente en la sección titulada "Seguridad de subprocesos".