0

How can the following code

while(1) {
  client_name_len = sizeof(struct sockaddr_in);
  newsockfd = accept(sockfd, (struct sockaddr *)&client_name, &client_name_len);
  if (newsockfd < 0) {
    perror("ERROR on accept");
    printf("Finished\n");
    close(sockfd);
    exit (EXIT_FAILURE);
  }
  printf("a:");
  pthread_t thread1;
  int *addr = (int*)malloc(sizeof(int));
  *addr = newsockfd;
  pthread_create( &thread1, NULL, &ProcessClient, (void*)addr);
}

produce the following output:

a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:ERROR on accept: Too many open files
a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:Finished

The problem is that perror("ERROR on accept"), printf("Finished\n") and printf("a:") are executed in the same thread, but the output is mixed.

ProcessClient does not output anything and does not create any threads. sockfd is a standard listening tcp socket.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
Dimannn
  • 73
  • 5

2 Answers2

2

The printf("a:"); and printf("Finished\n"); are buffered I/O going to stdout.

perror("ERROR on accept"); is unbuffered (or immediately flushed) I/O going to stderr.

So the many a:'s that show up after the ERROR on accept: Too many open files were actually printf()'ed before, but buffering makes them show up later on the console.

See https://stackoverflow.com/a/3746795/12711 for details and methods to solve the problem.

Community
  • 1
  • 1
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
1

As Michael pointed out, the first problem is that you're using two different streams (stdout and stderr), and that one is buffered while the other is unbuffered. However, you're also breaking the output up into multiple stdio calls, which makes it non-atomic. I would forst recommend either replacing the perror with:

printf("ERROR on accept: %s\n", strerror_l(errno));

or switching the other printf calls to use fprintf on stderr, so that you're consistent about which stream you're writing to.

Then, to make it atomic, call flockfile(f) at the beginning of your function and funlockfile(f) before you return (where f is replaced by whichever of stdout or stderr you choose to use). Or if you really still want to use both, you could lock both of them...

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711