Столкнулся с проблемой пропадания строк при многопоточной записи в STDOUT_FILENO (т.е. write(), не fwrite()).
Нашёл в интернете одну прошлогоднюю программу с описанием подобной проблемы и слегка её подпилил:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#define NTHREADS 10
volatile int flag = 0;
void *start(void *arg) {
char msg[255];
int res;
snprintf(msg, sizeof(msg), "hi from %"PRIxPTR"\n", (uintptr_t)arg);
if ((uintptr_t)arg == NTHREADS - 1)
flag = 1;
while (!flag) ; /* thread barrier */
#if 1
res = write(STDOUT_FILENO,msg,strlen(msg));
if (res != strlen(msg))
fprintf(stderr,"Failure: %i %s\n",res,strerror(res));
#else
fputs(msg,stdout);
#endif
#if 1 /* work extra hard to flush output (makes no difference) */
fflush(NULL);
fsync(STDOUT_FILENO);
sync();
#endif
return NULL;
}
int main() {
uintptr_t i;
pthread_t id[NTHREADS];
for (i =0 ; i < sizeof(id) / sizeof(id[0]); i++) {
int ret = pthread_create(&(id[i]),NULL,&start,(void *)i);
if (ret)
fprintf(stderr, "pthread_create: %s\n", strerror(ret));
}
for (i =0 ; i < sizeof(id) / sizeof(id[0]); i++) {
pthread_join(id[i], NULL);
}
return 0;
}
Компилируем:
$ gcc -Wall tmp.c -lpthread
Запускаем:
$ ./a.out | wc -l 10
Кажется, что всё нормально, но перенаправим вывод в файл, и начнутся чудеса:
$ ./a.out >o && wc -l o 2 o $ ./a.out >o && wc -l o 2 o $ ./a.out >o && wc -l o 4 o $ ./a.out >o && wc -l o 3 o $ ./a.out >o && wc -l o 3 o $ ./a.out >o && wc -l o 2 o $ ./a.out >o && wc -l o 3 o
Но если перенаправлять в существующий файл (дописыванием в конец):
$ rm o && touch o && ./a.out >> o && wc -l o 10 o $ rm o && touch o && ./a.out >> o && wc -l o 10 o $ rm o && touch o && ./a.out >> o && wc -l o 10 o
ОС - убунта 11.4. Под рукой есть солярка, на ней проблема не наблюдается. Объясните, пожалуйста, в чём может быть проблема?