[C] server, socket, thread-safeness of stdio.h functions

Hallo!
I wrote a webserver in C under FreeBSD...

SHARED DATA
FILE* log_file;
// other data

MAIN
fp = fopen(log_file);
// other inizializations
// create the thread pool
while(1) {
// 1) accept an incoming connection from a client;
// 2) assign the request to a free thread of the pre-allocated pool
// -) write the operations you do in the log_file and on stdout
};

THREADS of the pool BODY
// inizializations
while(1) {
// 1) handle a request assigned from main;
// -) write the operations you do in the log_file and on stdout
};

Now the questions:
i) The threads use the same file pointer (fp) to write in the log_file. Are there problems if more threads try to write using fprint() at the same time in the log_file? Are there precautions to take? Wich?

ii) Same question but for stdout using printf().

iii) Each thread of the pool has to open [fopen()], read [fread()] and close [fclose()] the file requested from the client before sending it. It could appen that 2 or more threads has to send the same file X to the clients so each thread will do fopen(), fread() and fclose() on the file X. Each thread will use for this operations its own file pointer. Are there precautions to take? Wich?

iv) My server can be terminated only by CTRL-C from the shell so it's not a clean exit because main is accepting connections, threads are handling requests, sockets and files are still open, dinamic memory is allocated...
Since a webserver should run for days or months continuosly and should be stopped quite never is it important to close it in a clean mode or is it only important that it works well when it's on? Which methods are usually used to communicate the server that it's time to end?

Sorry for all my qustions and many thanks to all who will be so kind to reply me. :)

Have a nice day!

F.
 
glibc manual says that any operation on a stream (i.e. fprintf(), printf()) in multi-threaded apps can be in the same way as in single-threaded ones because POSIX requires that stream functions are atomic (implicit locking).
Have a look here

As for the program's termination, catch SIGINT. Write your signal handler and call exit() which closes all I/O streams (not file descriptors) or you can use a very useful function atexit(3)
 
Back
Top