Discussion on the atomicity problem of error_log function output in PHP _php tutorial

Source: Internet
Author: User

Discussion on the atomicity of the output content of Error_log function in PHP


A few days ago to discuss with colleagues how to ensure that the Error_log output log in a login PHP has a unique identity header, the conclusion is the player account + current time + random number, in our current user volume level conditions should be to meet the demand, of course, this is not the focus of this article.

After identifying this simple scenario, I was thinking about two issues that are also the focus of this article today:

Can the 1.error_log call guarantee that the output is complete?

2. If it is complete, how is it guaranteed?

Verification began, initially thought Error_log call in the target file will be added to the file lock, directly read the source (php5.6.12):

From:basic_functions.c

PHPAPI int _php_error_log_ex (int opt_err, char *message, int message_len, char *opt, char *headers tsrmls_dc)/* {{*/{PH P_stream *stream = Null;switch (opt_err) {case 1:/*send an email */if (!php_mail (OPT, PHP error_log message, message, Heade RS, NULL tsrmls_cc)) {return FAILURE;} Break;case 2:/*send to an address */php_error_docref (NULL tsrmls_cc, e_warning, TCP/IP option not available!); Return failure;break;case 3:/*save to a file */stream = Php_stream_open_wrapper (opt, a, Ignore_url_win | Report_errors, NULL); if (!stream) {return FAILURE;} Php_stream_write (stream, message, Message_len);p Hp_stream_close (stream); Break;case 4:/* Send to SAPI */if (sapi_ Module.log_message) {sapi_module.log_message (message tsrmls_cc);} else {return FAILURE;} Break;default:php_log_err (message tsrmls_cc); return SUCCESS;} /* }}} */

From:streams.c

/* Writes a buffer directly to a stream, using multiple of the chunk size */static size_t _php_stream_write_buffer (php_str EAM *stream, const char *BUF, size_t count tsrmls_dc) {size_t didwrite = 0, towrite, justwrote;/* If we have a seekable st Ream we need to ensure this data is written in the * current stream->position. This means invalidating the read buffer and then * performing a low-level seek */if (Stream->ops->seek && (s Tream->flags & php_stream_flag_no_seek) = = 0 && stream->readpos! = stream->writepos) {stream-> Readpos = Stream->writepos = 0;stream->ops->seek (Stream, Stream->position, Seek_set, &stream-> Position tsrmls_cc);} while (Count > 0) {towrite = Count;if (Towrite > stream->chunk_size) towrite = Stream->chunk_size;justwrote = S Tream->ops->write (Stream, buf, Towrite tsrmls_cc);/* Convert Justwrote to a integer, since normally it is unsigned */if ((int) justwrote > 0) {buf + = justwrote;count-= Justwrote;didwrite + = justwrote;/* only screw with the buffer if we can seek, otherwise we lose data * buffered from FIFO S and sockets */if (Stream->ops->seek && (stream->flags & php_stream_flag_no_seek) = = 0) {Stream-&gt ;p osition + = Justwrote;}} else {break;}} return didwrite;}

By looking at the source file, Error_log just open the file in O_append mode, then it is write buf, OK, not see the file lock shadow. The problem is also obvious, write may be called multiple times, then it is basically determined that MSG is not guaranteed to be atomic output, multiple write makes this problem more serious.

Multiple write cannot guarantee atomic operation, so what about a single time?

1.from:man Write

o_append, the file offset is first set to the end of the       file before writing.  The       adjustment of the file offset and the write operation is performed as an       atomic step.

2.from:man Write

Atomic/non-atomic:a Write is Atomic if the whole amount written in one operation are not interleaved with data from any OT Her process. This was useful when there was multiple writers sending data to a single reader. Applications need to know what large a write request can be expected to be performed atomically. This maximum is called {pipe_buf}. This volume of IEEE Std 1003.1-2001 does not say whether write requests for more than {Pipe_buf} bytes is atomic, but req Uires that writes of {pipe_buf} or fewer bytes shall is atomic.

Man said that the approximate meaning is that if it is o_append mode, the location of the end of the file and the write call is an atomic operation, there will be no write at the end of the file needs to be adjusted, resulting in dislocation. The current atomicity guarantees only open and after the first write, and subsequent write is not guaranteed. Like Error_log, if the buf is too long, there is no guarantee that the BUF will be fully output once the write is repeated.

Keep going, then is the one-time write atomic? Man also gives the answer, no, only the data to be written less than equals pipe_buf to ensure atomic operation.

The question has been answered theoretically, and the following experiment has been validated:

test_error_log.php

 
  
check_line.py

filename =./append.txtfor line in open (filename):    print len
test.sh

#!/bin/bash rm-f append.txtfor ((counter=0; counter < ++counter) do    php test_error_log.php $counter $ & ;d onesleep 2#python check_line.py > A.txtpython check_line.py | Sort | Uniq-c



Verify the idea: in the output msg finally add line break, if the output of each line and the initial buf size is the same, the error_log complete output, verified that the kernel 3.5.0-23 pipe_buf 8k,8k error_log output can be guaranteed intact, Otherwise there is a risk of confusion.

http://www.bkjia.com/PHPjc/1050842.html www.bkjia.com true http://www.bkjia.com/PHPjc/1050842.html techarticle discussion on the atomicity of the output of error_log function in PHP a few days ago to discuss with colleagues how to ensure that the Error_log output log has a unique identity header in a login PHP call, the conclusion is to play ...

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.