PHP 8.1: New fsync and fdatasync functions

Version8.1
TypeNew Feature

PHP 8.1 adds two new functions to the group of file system functions.

PHP already has fflush function that flushes the potentially buffered data to the underlying operating system. fflush function is often used after write operations (fwrite calls), to make sure the PHP's internal buffers are flushed to the operating system.

The new fsync and fdatasync functions are similar to fflush, but they also request the operating system to flush the operating systems write buffers to the actual storage media.

fsync and fdatasync functions can be useful in applications that consistent and persistent storage is important. These functions only return true if the operating system indicates the data has been flushed to the storage media.

  • fsync: Synchronizes changes to the file (including meta-data)
  • fdatasync: Synchronizes data (but not meta-data) to the file.

fsync function

The fsync function synchronizes changes to the file, including its meta-data. This is similar to fflush, but it also instructs the operating system to write to the storage media.

Synopsis

/**
 * @param resource $stream
 */
function fsync($stream): bool {}

Passing a non-resource causes a \TypeError exception:

fsync('test.txt');
Fatal error: Uncaught TypeError: fsync(): supplied resource is not a valid stream resource in ...:...

If a resource object is passed, but if it does not support fsync operations, a warning will be raised:

$fh = fopen('memory://test');
fsync($fh);
Warning: fsync(): Can't fsync this stream! in ... on line ...

fdatasync function

The fdatasync function synchronizes stream contents to storage media, just like fsync does, but it does not synchronize file meta-data. Note that this function is only effectively different in POSIX systems. In Windows, this function is aliased to fsync.

Synopsis

/**
 * @param resource $stream
 */
function fdatasync($stream): bool {}

Error handling is similar to the fsync function.

Usage Example

$file = 'test.txt';

$fh = fopen($file, 'w');
fwrite($fh, 'test data');
fwrite($fh, "\r\n");
fwrite($fh, 'additional data');

fsync($fh);
fclose($fh);

The fsync (or fdatasync) call ensures the operating system is requested to write the data to the storage during the fsync call, in case the data was buffered by PHP or the operating system. The function call will be blocked until the data is written to storage.

Stream Wrapper Support

PHP provides stream wrappers that abstracts internal implementation details. File system functions such as fopen, fwrite, and unlink can then be used across all registered stream wrappers, without having to use different functions for each stream protocol.

Built-in stream wrappers
Only the built-in file stream wrapper supports fsync and fdatasync functions.

Custom stream wrappers
Custom stream wrappers registered with stream_wrapper_register cannot declare their own fsync and fdatasync implementations.

fflush vs fsync vs fdatasync comparison

fflush fsync fdatasync
Availability PHP >= 4.0.1 PHP >= 8.1 PHP >= 8.1
Functionality Flushes buffers to OS for writing Flushes to OS and requests to write to storage, and update meta-data Flushes to OS and requests to write to storage, but only data
Stream Wrapper support

Backwards Compatibility Impact

Both fsync and fdatasync functions are new functions added to the root namespace.

If there are any existing functions with fsync or fdatasync names, this change will cause a function re-declaration fatal error. The top 1,000 packages according to packagist.org download statistics, and a GitHub search shows that there are no existing packages that redeclare functions with fsync or fdatasync names.

The new fsync and fdatasync functions interact with the underlying operating system, and it is not possible to effectively polyfill these functions to older PHP versions.

However, the PECL extension eio (pecl.php.net/GitHub) provides eio_fsync and eio_fdatasync functions that achieve similar results. Note that the function signatures are different, and may not be fully compatible with the implementation in PHP 8.1.


RFC Discussion Implementation