2

Here is process a and b, both of which are multithreaded.

  1. a forks b and b immediatly execs one new program;
  2. a dups and freopens stderr to the logfile (a is defacto apache's httpd2.22)
  3. b inherits the opened stderr from a. ( i am adapting apache httpd, b is my program), and b uses fprintf(stderr....) for logging
  4. so a, b share the same file for logging
  5. there is no lock mechanism for a, b to write log

I found that some log msg are interleaving, and a little bit of log msg got lost.

Can the two writers to the same file implicitly lock each other out?

The more important question is: If we use fprintf only within one single multithreaded process, fprintf is thread safe, i.e. one call of fprintf won't intervene another fprintf call in another thread? Many articles said this, but this is not easy to ensure myself, so I ask for help here.

A: the code for duplicate the fd is like this:

......
rv = apr_file_dup2(stderr_log, s_main->error_log, stderr_p);//dup the stderr to the logfile
apr_file_close(s_main->error_log);//here ,2 fd point to the same file description,so close one of 

then

B:apache it self use this manner for logging:

......
if (rv != APR_SUCCESS) {
    ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s_main, ".........");

C:for convenience,i logging in this way:

fprintf(stderr,".....\n")

I am quite sure apache and me use the same fd for file writing.

4

1 回答 1

8

如果您使用单个FILE对象对打开的文件执行输出,则对该文件的整个fprintf调用FILE将是原子的,即FILE在调用期间保持锁定fprintf。由于 aFILE对单个进程的地址空间是本地的,因此这种设置仅适用于多线程应用程序;它不适用于多进程设置,其中几个不同的进程正在访问FILE引用同一底层打开文件的单独对象。即使您在fprintf这里使用,每个进程都有自己的FILE它可以锁定和解锁,而其他人看不到更改,因此写入最终可能是交错的。有几种方法可以防止这种情况发生:

  1. 在共享内存中分配一个同步对象(例如进程共享的信号量或互斥锁),并使每个进程在写入文件之前获得锁(因此一次只能写入一个进程);或者

  2. 使用文件系统级别的咨询锁定,例如fcntl锁定或(非 POSIX)BSDflock接口;或者

  3. 不要直接写入日志文件,而是写入另一个进程将馈送到日志文件的管道。只要它们小于PIPE_BUF字节长度,就可以保证(通过 POSIX)对管道的写入是原子的。在这种情况下您不能使用fprintf(因为它可能会执行多个底层写入操作),但您可以使用snprintf-sizedPIPE_BUF缓冲区,后跟write.

于 2012-07-26T07:51:57.087 回答