63 lines
2.4 KiB
Diff
63 lines
2.4 KiB
Diff
commit 10af00f7a135c85796a9c4c75228358b8898da5c
|
|
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
|
Date: Fri Mar 14 10:18:21 2025 -0400
|
|
|
|
tst-fopen-threaded: Only check EOF for failing read
|
|
|
|
The fread race checker looks for EOF in every thread, which is incorrect
|
|
since threads calling fread successfully could lag behind and read the
|
|
EOF condition, resulting in multiple threads thinking that they
|
|
encountered an EOF.
|
|
|
|
Only look for EOF condition if fread fails to read a char. Also drop
|
|
the clearerr() since it could mask the failure of another reader, thus
|
|
hiding a test failure.
|
|
|
|
Finally, also check for error in the stream for completeness.
|
|
|
|
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
|
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
|
|
|
diff --git a/sysdeps/pthread/tst-fopen-threaded.c b/sysdeps/pthread/tst-fopen-threaded.c
|
|
index 5c792c93e3711621..ade58ad19eb209d1 100644
|
|
--- a/sysdeps/pthread/tst-fopen-threaded.c
|
|
+++ b/sysdeps/pthread/tst-fopen-threaded.c
|
|
@@ -64,19 +64,27 @@ threadReadRoutine (void *argv)
|
|
/* Wait for all threads to be ready to read. */
|
|
xpthread_barrier_wait (&barrier);
|
|
|
|
- ret =
|
|
- fread (&read_buffer, sizeof (char), sizeof (read_buffer), my_data->fd);
|
|
- if (feof (my_data->fd) != 0)
|
|
+ ret = fread (&read_buffer, 1, sizeof (read_buffer), my_data->fd);
|
|
+ /* If no data is returned (we read only 1 byte, so there's no short read
|
|
+ situation here), look for EOF flag and record it in MY_DATA. The EOF flag
|
|
+ is not cleared because that could result in a test failure being masked
|
|
+ when two threads fail to read and one of them clears error/EOF flags
|
|
+ before the second one has the chance to observe it.
|
|
+
|
|
+ Successful readers could still see the EOF if they fall behind the failing
|
|
+ read when calling feof(), which could result in a false test failure. To
|
|
+ avoid this race, we only make the failing reader check for EOF or
|
|
+ error. */
|
|
+ if (ret == 0)
|
|
{
|
|
- clearerr (my_data->fd);
|
|
- my_data->eof = true;
|
|
+ if (feof (my_data->fd) != 0)
|
|
+ my_data->eof = true;
|
|
+ else
|
|
+ FAIL_EXIT1 ("fread failed (ferror: %d): %m", ferror (my_data->fd));
|
|
}
|
|
else
|
|
- {
|
|
- TEST_COMPARE (ret, 1);
|
|
- /* Save the read value. */
|
|
- my_data->value = read_buffer;
|
|
- }
|
|
+ /* Save the read value. */
|
|
+ my_data->value = read_buffer;
|
|
TEST_COMPARE (ferror (my_data->fd), 0);
|
|
return NULL;
|
|
}
|