Skip to content

Conversation

marc-mabe
Copy link
Contributor

@marc-mabe marc-mabe commented Jul 21, 2025

This pull request refactors how PHP internally handles current time retrieval and time measurement, introducing a more consistent and portable approach. The primary goals are to encapsulate platform-specific differences, improve time resolution, and prepare for long-term compatibility (e.g., Y2038 on WIN64).

Key Changes

  • Introduced zend_time.h
    A new internal header that abstracts system time functions, replacing direct usage of <time.h> and related platform-specific APIs.

  • Added zend_realtime_spec
    A unified wrapper around clock_gettime(), timespec_get(), gettimeofday(), and time() using the real/wall clock.
    Returns a timespec structure with nanosecond precision (when available).

  • Defined zend_realtime_get macro
    A lightweight macro wrapping time(NULL) for simple, low-resolution time retrieval.

  • Introduced zend_monotime_fallback
    A macro that maps to zend_hrtime or falls back to zend_realtime_spec.
    Useful for time measurements (e.g. timeout handling) where monotonic time is preferred, but wall time is an acceptable fallback.

  • Provided helper macros
    Added utilities to simplify usage of timeval and timespec structures.

  • Replaced direct system time API usage
    Internal calls to system time functions now use zend_realtime_* or zend_monotime_fallback.

  • Standardized time representation
    Transitioned to timespec for current time where appropriate, while retaining timeval for files and stream-related functionality.

Benefits

  • Improved Portability and Readability
    Platform-specific time logic is encapsulated, reducing conditionals and improving clarity.

  • Guaranteed Time API Availability
    The new abstraction ensures time can always be retrieved via a fallback chain:
    clock_gettime()timespec_get()gettimeofday()time()

  • Y2038 Compatibility on WIN64
    Addresses issues caused by long in timeval.tv_sec on 64-bit Windows systems.

    Related issue: #17856 – time() and Y2038 problem on 64-bit Windows

  • Improved Resolution for Time Functions
    microtime() and gettimeofday(true) now offer better time precision without breaking backward compatibility.

  • Removed Redundant Availability Checks
    Previously unverified use of gettimeofday() has been replaced by a robust fallback mechanism.
    Conditional checks for microtime(), gettimeofday(), and uniqid() have been removed.

@marc-mabe marc-mabe force-pushed the current_time_wrapper branch 2 times, most recently from 7e3d98c to fdabd9b Compare July 26, 2025 08:46
@marc-mabe marc-mabe force-pushed the current_time_wrapper branch from 1058493 to 9429859 Compare July 28, 2025 07:02
@marc-mabe marc-mabe requested a review from devnexen as a code owner September 23, 2025 06:12
@marc-mabe marc-mabe force-pushed the current_time_wrapper branch from 315f346 to 956b7a0 Compare October 4, 2025 19:57
@marc-mabe marc-mabe changed the title Refactor basic time usages Refactor Internal Time Retrieval Handling for Improved Consistency and Resolution Oct 5, 2025
@marc-mabe marc-mabe force-pushed the current_time_wrapper branch from 956b7a0 to 88ec473 Compare October 5, 2025 05:41
@marc-mabe marc-mabe force-pushed the current_time_wrapper branch from 88ec473 to abf0e46 Compare October 19, 2025 02:53
@marc-mabe marc-mabe requested a review from TimWolla October 19, 2025 03:14
@marc-mabe
Copy link
Contributor Author

marc-mabe commented Oct 19, 2025

@TimWolla I think this is ready to go now. Please could you have another look and/or point me to the right person to ping?

@bukka Please could you help me for how to fix the failing unit test (expecting gettimeofday but now using zend_monotime_fallback)

Copy link
Member

@TimWolla TimWolla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had a rudimentary first look.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please make all the macros that could be (inline) functions a proper function? I think that should be all of them.

Please also properly “namespace” all the symbols by prefixing them with zend_time_*.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please make all the macros that could be (inline) functions a proper function? I think that should be all of them.

👍

Please also properly “namespace” all the symbols by prefixing them with zend_time_*.

For the zend_realtime_spec, zend_realtime_get and zend_monotime_fallback functions I felt it sounds more natural and it's obvious these functions belong to time.
Would zend_time_real_get, zend_time_real_spec and zend_time_mono_fallback better match with your expected naming scheme?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would zend_time_real_get, zend_time_real_spec and zend_time_mono_fallback better match with your expected naming scheme?

Yes. While it might sound a little awkward, I find it valuable to easily locate where the function is declared.

Comment on lines +19 to +40
ZEND_API void zend_realtime_spec(struct timespec *ts) {
#if defined(HAVE_CLOCK_GETTIME)

clock_gettime(CLOCK_REALTIME, ts);

#elif defined(HAVE_TIMESPEC_GET)

timespec_get(ts, TIME_UTC);

#elif defined(HAVE_GETTIMEOFDAY)

struct timeval tv;
gettimeofday(&tv, NULL);
zend_time_val2spec(tv, ts);

#else

ts->tv_sec = zend_realtime_get();
ts->tv_nsec = 0;

#endif
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these all infallible at runtime? Complexity-wise this could also be an inline function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of these functions can return an error in case of using wrong/unsupported arguments.
On the same time here only the most basic functionality is used and in the previous implementation error returns where not checked.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the previous implementation error returns where not checked.

Sure, but I don't think this is a reason that this should not be improved. Though it certainly raises the question if a broken clock is even recoverable.

Perhaps add a (void) in front to make it explicit that we don't want to handle the errors?

Copy link
Member

@TimWolla TimWolla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more bits. I'm approximately halfway through the PR. Feel free to already make the requested changes with regard to the removal of the macros, this probably saves us both a review cycle.

time->us = microsecond;
}

static void php_date_get_current_time_with_fraction(time_t *sec, suseconds_t *usec)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one can probably be removed entirely now.


PHPAPI time_t php_time(void);
/* DEPRECATED, use zend_realtime_get() instead */
#define php_time() zend_realtime_get()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please leave this as a (inline) function and add ZEND_ATTRIBUTE_DEPRECATED so that folks actually notice that this is deprecated?

@marc-mabe
Copy link
Contributor Author

Some more bits. I'm approximately halfway through the PR. Feel free to already make the requested changes with regard to the removal of the macros, this probably saves us both a review cycle.

I'll be able to continue my work on it from tomorrow evening.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants