Test that errno is set to 0 at program startup

Message ID 20240911004315.167590-1-amerey@redhat.com
State Superseded
Headers
Series Test that errno is set to 0 at program startup |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed

Commit Message

Aaron Merey Sept. 11, 2024, 12:43 a.m. UTC
  Add new testcase elf/tst-startup-errno.c which tests that errno is set
to 0 at first ELF constructor execution and at the start of the
program's main function.

Tested for x86_64
---
 elf/Makefile            |  1 +
 elf/tst-startup-errno.c | 49 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)
 create mode 100644 elf/tst-startup-errno.c
  

Comments

Andreas Schwab Sept. 11, 2024, 7:41 a.m. UTC | #1
On Sep 10 2024, Aaron Merey wrote:

> +static int
> +do_test (void)
> +{
> +  TEST_COMPARE (errno, 0);
> +  TEST_COMPARE (get_ctor_errno (), 0);
> +
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>

That only tests that the test driver does not modify errno, which is
uninteresting.
  
Maciej W. Rozycki Sept. 11, 2024, 11:31 a.m. UTC | #2
On Wed, 11 Sep 2024, Andreas Schwab wrote:

> > +static int
> > +do_test (void)
> > +{
> > +  TEST_COMPARE (errno, 0);
> > +  TEST_COMPARE (get_ctor_errno (), 0);
> > +
> > +  return 0;
> > +}
> > +
> > +#include <support/test-driver.c>
> 
> That only tests that the test driver does not modify errno, which is
> uninteresting.

 Good point.  The test is so simple that I think it does not need to use 
the driver as there's hardly if anything that could hang here so that it 
would require the driver's intervention (and if it did hang, so could the 
test driver anyway).

 Alternatively with some macro trickery we could arrange for test driver's 
`main' to be called second from test's local `main', so that things like 
TEST_COMPARE work as expected (and `do_test' only checks copies of `errno' 
values recorded previously).

  Maciej
  
Carlos O'Donell Sept. 13, 2024, 12:24 p.m. UTC | #3
On 9/11/24 7:31 AM, Maciej W. Rozycki wrote:
> On Wed, 11 Sep 2024, Andreas Schwab wrote:
> 
>>> +static int
>>> +do_test (void)
>>> +{
>>> +  TEST_COMPARE (errno, 0);
>>> +  TEST_COMPARE (get_ctor_errno (), 0);
>>> +
>>> +  return 0;
>>> +}
>>> +
>>> +#include <support/test-driver.c>
>>
>> That only tests that the test driver does not modify errno, which is
>> uninteresting.
> 
>  Good point.  The test is so simple that I think it does not need to use 
> the driver as there's hardly if anything that could hang here so that it 
> would require the driver's intervention (and if it did hang, so could the 
> test driver anyway).

Yes, I forgot the test driver gets entirely in the way.

I suggest we simplify the test then:

 * Drop "#include <support/test-driver.c>"
 * Use "int main()" directly.
 * Directly check the values and exit(1) if they are not zero.
 
>  Alternatively with some macro trickery we could arrange for test driver's 
> `main' to be called second from test's local `main', so that things like 
> TEST_COMPARE work as expected (and `do_test' only checks copies of `errno' 
> values recorded previously).

No, I think a bare main() here is simplest, it shouldn't hang, if it does then we have
much more complex problems.
  
Zack Weinberg Sept. 13, 2024, 1:24 p.m. UTC | #4
On Tue, Sep 10, 2024, at 8:43 PM, Aaron Merey wrote:
> Add new testcase elf/tst-startup-errno.c which tests that errno is set
> to 0 at first ELF constructor execution and at the start of the
> program's main function.

If a C++ global constructor sets errno to a nonzero value, aren't we obliged to preserve that value, and thus have  errno be nonzero on entry to main?

zw
  
Aaron Merey Sept. 19, 2024, 3:27 p.m. UTC | #5
Hi Zack,

On Fri, Sep 13, 2024 at 9:25 AM Zack Weinberg <zack@owlfolio.org> wrote:
>
> On Tue, Sep 10, 2024, at 8:43 PM, Aaron Merey wrote:
> > Add new testcase elf/tst-startup-errno.c which tests that errno is set
> > to 0 at first ELF constructor execution and at the start of the
> > program's main function.
>
> If a C++ global constructor sets errno to a nonzero value, aren't we obliged to preserve that value, and thus have  errno be nonzero on entry to main?

Yes but this is just testing that errno stays set to zero when not
modified by an ELF constructor.

Aaron
  
Zack Weinberg Sept. 19, 2024, 3:51 p.m. UTC | #6
On Thu, Sep 19, 2024, at 11:27 AM, Aaron Merey wrote:
> On Fri, Sep 13, 2024 at 9:25 AM Zack Weinberg <zack@owlfolio.org> wrote:
>> On Tue, Sep 10, 2024, at 8:43 PM, Aaron Merey wrote:
>> > Add new testcase elf/tst-startup-errno.c which tests that errno is
>> > set to 0 at first ELF constructor execution and at the start of the
>> > program's main function.
>>
>> If a C++ global constructor sets errno to a nonzero value, aren't we
>> obliged to preserve that value, and thus have errno be nonzero on
>> entry to main?
>
> Yes but this is just testing that errno stays set to zero when not
> modified by an ELF constructor.

Ah, I misread your code, I thought it was testing that errno is zero
on entry to main *even if* an ELF constructor sets it to nonzero.

In that case I suggest that there should be an additional test with
an ELF constructor that *does* set errno to nonzero and then we check
in main that it still has the same value.

zw
  

Patch

diff --git a/elf/Makefile b/elf/Makefile
index 00622ace9d..be1a99ea26 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -457,6 +457,7 @@  tests += \
   tst-single_threaded-pthread \
   tst-sonamemove-dlopen \
   tst-sonamemove-link \
+  tst-startup-errno \
   tst-thrlock \
   tst-tls-dlinfo \
   tst-tls-ie \
diff --git a/elf/tst-startup-errno.c b/elf/tst-startup-errno.c
new file mode 100644
index 0000000000..0db72a60fa
--- /dev/null
+++ b/elf/tst-startup-errno.c
@@ -0,0 +1,49 @@ 
+/* Test the value of errno at program startup.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <support/check.h>
+
+/* Verify that errno is 0 at first ELF constructor execution and at
+   the start of main.  */
+
+static void set_ctor_errno (void) __attribute__((constructor));
+static int ctor_errno = -1;
+
+static void
+set_ctor_errno (void)
+{
+  ctor_errno = errno;
+}
+
+static int
+get_ctor_errno (void)
+{
+  return ctor_errno;
+}
+
+static int
+do_test (void)
+{
+  TEST_COMPARE (errno, 0);
+  TEST_COMPARE (get_ctor_errno (), 0);
+
+  return 0;
+}
+
+#include <support/test-driver.c>