stdio-common: Avoid spurious mtime/ctime-related failure in tst-fseek
Checks
| Context |
Check |
Description |
| redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
| linaro-tcwg-bot/tcwg_glibc_build--master-arm |
success
|
Build passed
|
| redhat-pt-bot/TryBot-32bit |
success
|
Build for i686
|
| linaro-tcwg-bot/tcwg_glibc_check--master-arm |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 |
success
|
Test passed
|
Commit Message
The test seems to use the timestamps to verify that the file
has been written as part of the buffer flush. Any change should
be sufficient. Using the nanosecond field means that if the
second field does not change due to clock rounding differences,
the test does not fail unexpectedly.
This was originally observed as a failure on s390x-linux-gnu:
=====FAIL: stdio-common/tst-fseek.out=====
350: st_ctime not changed
355: st_mtime not changed
436: SEEK_END works
468: SEEK_END works
---
stdio-common/tst-fseek.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
base-commit: 13c114c10bd3b665c1f11bd5f843bfe5e8238efb
Comments
On Sep 02 2026, Florian Weimer wrote:
> diff --git a/stdio-common/tst-fseek.c b/stdio-common/tst-fseek.c
> index 086ede5967..64f1e0a057 100644
> --- a/stdio-common/tst-fseek.c
> +++ b/stdio-common/tst-fseek.c
> @@ -345,12 +345,14 @@ do_test (void)
> printf ("%d: st_mtime not updated\n", __LINE__);
> result = 1;
> }
> - if (st1.st_ctime >= st2.st_ctime)
> + if (st1.st_ctime >= st2.st_ctime
> + && st1.st_ctim.tv_nsec == st2.st_ctim.tv_nsec)
> {
> printf ("%d: st_ctime not changed\n", __LINE__);
> result = 1;
> }
> - if (st1.st_mtime >= st2.st_mtime)
> + if (st1.st_mtime >= st2.st_mtime
> + && st1.st_mtim.tv_nsec == st2.st_mtim.tv_nsec)
> {
> printf ("%d: st_mtime not changed\n", __LINE__);
> result = 1;
What about the other two conditions before those? It's also strange to
use >= instead of ==, as if the test tries to handle time going
backwards in some way.
On 02/09/26 08:47, Florian Weimer wrote:
> The test seems to use the timestamps to verify that the file
> has been written as part of the buffer flush. Any change should
> be sufficient. Using the nanosecond field means that if the
> second field does not change due to clock rounding differences,
> the test does not fail unexpectedly.
>
> This was originally observed as a failure on s390x-linux-gnu:
>
> =====FAIL: stdio-common/tst-fseek.out=====
> 350: st_ctime not changed
> 355: st_mtime not changed
> 436: SEEK_END works
> 468: SEEK_END works
>
Maybe use TEST_TIMESPEC_EQUAL_OR_AFTER instead?
> ---
> stdio-common/tst-fseek.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/stdio-common/tst-fseek.c b/stdio-common/tst-fseek.c
> index 086ede5967..64f1e0a057 100644
> --- a/stdio-common/tst-fseek.c
> +++ b/stdio-common/tst-fseek.c
> @@ -345,12 +345,14 @@ do_test (void)
> printf ("%d: st_mtime not updated\n", __LINE__);
> result = 1;
> }
> - if (st1.st_ctime >= st2.st_ctime)
> + if (st1.st_ctime >= st2.st_ctime
> + && st1.st_ctim.tv_nsec == st2.st_ctim.tv_nsec)
> {
> printf ("%d: st_ctime not changed\n", __LINE__);
> result = 1;
> }
> - if (st1.st_mtime >= st2.st_mtime)
> + if (st1.st_mtime >= st2.st_mtime
> + && st1.st_mtim.tv_nsec == st2.st_mtim.tv_nsec)
> {
> printf ("%d: st_mtime not changed\n", __LINE__);
> result = 1;
>
> base-commit: 13c114c10bd3b665c1f11bd5f843bfe5e8238efb
* Andreas Schwab:
> On Sep 02 2026, Florian Weimer wrote:
>
>> diff --git a/stdio-common/tst-fseek.c b/stdio-common/tst-fseek.c
>> index 086ede5967..64f1e0a057 100644
>> --- a/stdio-common/tst-fseek.c
>> +++ b/stdio-common/tst-fseek.c
>> @@ -345,12 +345,14 @@ do_test (void)
>> printf ("%d: st_mtime not updated\n", __LINE__);
>> result = 1;
>> }
>> - if (st1.st_ctime >= st2.st_ctime)
>> + if (st1.st_ctime >= st2.st_ctime
>> + && st1.st_ctim.tv_nsec == st2.st_ctim.tv_nsec)
>> {
>> printf ("%d: st_ctime not changed\n", __LINE__);
>> result = 1;
>> }
>> - if (st1.st_mtime >= st2.st_mtime)
>> + if (st1.st_mtime >= st2.st_mtime
>> + && st1.st_mtim.tv_nsec == st2.st_mtim.tv_nsec)
>> {
>> printf ("%d: st_mtime not changed\n", __LINE__);
>> result = 1;
>
> What about the other two conditions before those? It's also strange to
> use >= instead of ==, as if the test tries to handle time going
> backwards in some way.
We haven't seen those failing. Should we delete them? Then we would
end up with this?
diff --git a/stdio-common/tst-fseek.c b/stdio-common/tst-fseek.c
index 086ede5967..4fc38b09e0 100644
--- a/stdio-common/tst-fseek.c
+++ b/stdio-common/tst-fseek.c
@@ -325,32 +325,22 @@ do_test (void)
else
{
- time_t t;
/* Make sure the timestamp actually can be different. */
sleep (1);
- t = time (NULL);
if (fstat64 (fd, &st2) < 0)
{
printf ("%d: fstat64() after fseeko() failed\n\n", __LINE__);
result = 1;
}
- if (st1.st_ctime >= t)
- {
- printf ("%d: st_ctime not updated\n", __LINE__);
- result = 1;
- }
- if (st1.st_mtime >= t)
- {
- printf ("%d: st_mtime not updated\n", __LINE__);
- result = 1;
- }
- if (st1.st_ctime >= st2.st_ctime)
+ if (st1.st_ctime == st2.st_ctime
+ && st1.st_ctim.tv_nsec == st2.st_ctim.tv_nsec)
{
printf ("%d: st_ctime not changed\n", __LINE__);
result = 1;
}
- if (st1.st_mtime >= st2.st_mtime)
+ if (st1.st_mtime == st2.st_mtime
+ && st1.st_mtim.tv_nsec == st2.st_mtim.tv_nsec)
{
printf ("%d: st_mtime not changed\n", __LINE__);
result = 1;
Thanks,
Florian
On 2026-09-02 04:47, Florian Weimer wrote:
> Using the nanosecond field means that if the
> second field does not change due to clock rounding differences,
> the test does not fail unexpectedly.
What sort of clock rounding difference is hypothesized here? There's a call to sleep(1) between the two timestamps, POSIX requires sleep(1) to sleep for at least 1 second, so the test should be valid as-is.
If a clock-rounding difference can cause sleep(1) to sleep for slightly less than one second, that's a bug in 'sleep' that this test has exposed, and the bug should be fixed not the test.
If a clock-rounding difference could cause st_ctim to be truncated to less than one-second resolution, because (for example) the test is being run on a VFAT-like file system on s390x, a file system where st_ctim has only two-second resolution, then the fix to the test is to increase sleep(1) to sleep(2), and no other changes should be needed. (Or we should require that all tests be run in a file system with a one-second resolution or better.)
If the bug is observed because tests are being run in parallel, with some other test using clock_settime or equivalent to set the realtime clock, the proposed patch would not fix the problem in general; the fix would be to run clock-setting tests separately, so that they do not interfere with tests that assume the realtime clock is monotonic.
* Florian Weimer:
> The test seems to use the timestamps to verify that the file
> has been written as part of the buffer flush. Any change should
> be sufficient. Using the nanosecond field means that if the
> second field does not change due to clock rounding differences,
> the test does not fail unexpectedly.
>
> This was originally observed as a failure on s390x-linux-gnu:
>
> =====FAIL: stdio-common/tst-fseek.out=====
> 350: st_ctime not changed
> 355: st_mtime not changed
> 436: SEEK_END works
> 468: SEEK_END works
>
> ---
> stdio-common/tst-fseek.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/stdio-common/tst-fseek.c b/stdio-common/tst-fseek.c
> index 086ede5967..64f1e0a057 100644
> --- a/stdio-common/tst-fseek.c
> +++ b/stdio-common/tst-fseek.c
> @@ -345,12 +345,14 @@ do_test (void)
> printf ("%d: st_mtime not updated\n", __LINE__);
> result = 1;
> }
> - if (st1.st_ctime >= st2.st_ctime)
> + if (st1.st_ctime >= st2.st_ctime
> + && st1.st_ctim.tv_nsec == st2.st_ctim.tv_nsec)
> {
> printf ("%d: st_ctime not changed\n", __LINE__);
> result = 1;
> }
> - if (st1.st_mtime >= st2.st_mtime)
> + if (st1.st_mtime >= st2.st_mtime
> + && st1.st_mtim.tv_nsec == st2.st_mtim.tv_nsec)
> {
> printf ("%d: st_mtime not changed\n", __LINE__);
> result = 1;
>
> base-commit: 13c114c10bd3b665c1f11bd5f843bfe5e8238efb
This fix is related:
commit 0d28f1f1a07e3a4473fb87cfade9528e54fbffe0
Author: Yury Khrustalev <yury.khrustalev@arm.com>
Date: Mon Feb 2 14:06:38 2026 +0000
tests: posix: use cpu clock for sleep
On some emulated targets sleep may result in inconsistent wait
times which will lead to the failure of the tst-chmod test.
To account for this we use the CLOCK_PROCESS_CPUTIME_ID clock ID
while also consuming CPU time by repeatedly calling clock_gettime.
Reviewed-by: DJ Delorie <dj@redhat.com>
I'll probably submit something along those lines later.
Thanks,
Florian
On 2026-09-07 06:04, Florian Weimer wrote:
> This fix is related:
>
> commit 0d28f1f1a07e3a4473fb87cfade9528e54fbffe0
> Author: Yury Khrustalev<yury.khrustalev@arm.com>
> Date: Mon Feb 2 14:06:38 2026 +0000
>
> tests: posix: use cpu clock for sleep
>
> On some emulated targets sleep may result in inconsistent wait
> times which will lead to the failure of the tst-chmod test.
>
> To account for this we use the CLOCK_PROCESS_CPUTIME_ID clock ID
> while also consuming CPU time by repeatedly calling clock_gettime.
>
> Reviewed-by: DJ Delorie<dj@redhat.com>
>
> I'll probably submit something along those lines later.
That patch is basically saying "the 'sleep' function is buggy, so let's work around the bug in a CPU-intensive way." Wouldn't it be better to fix the 'sleep' function than to rewrite all tests using 'sleep'? After all, user code depends on 'sleep' too.
What causes the bug in the 'sleep' function? Is there a bug report for it?
@@ -345,12 +345,14 @@ do_test (void)
printf ("%d: st_mtime not updated\n", __LINE__);
result = 1;
}
- if (st1.st_ctime >= st2.st_ctime)
+ if (st1.st_ctime >= st2.st_ctime
+ && st1.st_ctim.tv_nsec == st2.st_ctim.tv_nsec)
{
printf ("%d: st_ctime not changed\n", __LINE__);
result = 1;
}
- if (st1.st_mtime >= st2.st_mtime)
+ if (st1.st_mtime >= st2.st_mtime
+ && st1.st_mtim.tv_nsec == st2.st_mtim.tv_nsec)
{
printf ("%d: st_mtime not changed\n", __LINE__);
result = 1;