* [PATCH] print extended assertion failures to stderr @ 2021-11-04 13:53 sotrdg sotrdg 2021-11-04 13:54 ` Jonathan Wakely 0 siblings, 1 reply; 7+ messages in thread From: sotrdg sotrdg @ 2021-11-04 13:53 UTC (permalink / raw) To: unlvsur unlvsur via Libstdc++ I think We better put entire function __replacement_assert into other translation unit Instead of putting stderr? Get Outlook for Android<https://aka.ms/AAb9ysg> ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] print extended assertion failures to stderr 2021-11-04 13:53 [PATCH] print extended assertion failures to stderr sotrdg sotrdg @ 2021-11-04 13:54 ` Jonathan Wakely [not found] ` <CH2PR02MB65229EA7D6AA4BCC9515F087B28D9@CH2PR02MB6522.namprd02.prod.outlook.com> 0 siblings, 1 reply; 7+ messages in thread From: Jonathan Wakely @ 2021-11-04 13:54 UTC (permalink / raw) To: sotrdg sotrdg; +Cc: unlvsur unlvsur via Libstdc++ On Thu, 4 Nov 2021 at 13:53, sotrdg sotrdg via Libstdc++ < libstdc++@gcc.gnu.org> wrote: > I think We better put entire function > > __replacement_assert > > into other translation unit Instead of putting stderr? > Why? ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <CH2PR02MB65229EA7D6AA4BCC9515F087B28D9@CH2PR02MB6522.namprd02.prod.outlook.com>]
[parent not found: <CACb0b4m7oddSaVMqDG61gDQ_++pC4nrJYRpPE3U6E+QRbyVNQA@mail.gmail.com>]
* Re: [PATCH] print extended assertion failures to stderr [not found] ` <CACb0b4m7oddSaVMqDG61gDQ_++pC4nrJYRpPE3U6E+QRbyVNQA@mail.gmail.com> @ 2021-11-04 14:17 ` sotrdg sotrdg 2021-11-04 15:13 ` Jonathan Wakely 0 siblings, 1 reply; 7+ messages in thread From: sotrdg sotrdg @ 2021-11-04 14:17 UTC (permalink / raw) To: unlvsur unlvsur via Libstdc++ i do have other arguments like no longer use none std compiler specific extensions or allow user to replace that function with linker in some environments. Get Outlook for Android<https://aka.ms/AAb9ysg> ________________________________ From: Jonathan Wakely <jwakely@redhat.com> Sent: Thursday, November 4, 2021 10:01:27 AM To: sotrdg sotrdg <euloanty@live.com> Subject: Re: [PATCH] print extended assertion failures to stderr On Thu, 4 Nov 2021 at 13:59, sotrdg sotrdg wrote: It reduces one function call Who cares if aborting the program takes an additional function call?! and reduces compilation time for each translation unit. That's a valid argument. As is the fact that __replacement_assert won't get inlined into its callers, keeping them smaller. But "reduces on function call" seems an absurd thing to care about in this case. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] print extended assertion failures to stderr 2021-11-04 14:17 ` sotrdg sotrdg @ 2021-11-04 15:13 ` Jonathan Wakely 0 siblings, 0 replies; 7+ messages in thread From: Jonathan Wakely @ 2021-11-04 15:13 UTC (permalink / raw) To: sotrdg sotrdg; +Cc: unlvsur unlvsur via Libstdc++ On Thu, 4 Nov 2021 at 14:19, sotrdg sotrdg via Libstdc++ <libstdc++@gcc.gnu.org> wrote: > > i do have other arguments like no longer use none std compiler specific extensions or allow user to replace that function with linker in some environments. What compiler-specific extensions? __builtin_abort()? That's just a way to call abort without including <stdlib.h> and is supported by all compilers that can use libstdc++. Supporting compilers that are nothing like GCC is not a goal. ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH] print extended assertion failures to stderr @ 2021-10-27 8:25 Jay Feldblum 2021-11-04 11:30 ` Jonathan Wakely 0 siblings, 1 reply; 7+ messages in thread From: Jay Feldblum @ 2021-10-27 8:25 UTC (permalink / raw) To: libstdc++, gcc-patches From: yfeldblum <yfeldblum@gmail.com> The stdout stream is reserved for output intentionally produced by the application. Assertion failures and other forms of logging must be emitted to stderr, not to stdout. It is common for testing and monitoring infrastructure to scan stderr for errors, such as for assertion failures, and to collect or retain them for analysis or observation. It is a norm that assertion failures match this expectation in practice. While `__builtin_fprintf` is available as a builtin, there is no equivalent builtin for `stderr`. The only option in practice is to use the macro `stderr`, which requires `#include <cstdio>`. It is desired not to add such an include to `bits/c++config` so the solution is to write and export a function which may be called by `bits/c++config`. This is expected to be API-compatible and ABI-compatible with caveats. Code compiled against an earlier libstdc++ will work when linked into a later libstdc++ but the stream to which assertion failures are logged is anybody's guess, and in practice will be determined by the link line and the choice of linker. This fix targets builds for which all C++ code is built against a libstdc++ with the fix. Alternatives: * This, which is the smallest change. * This, but also defining symbols `std::__stdin` and `std::__stdout` for completeness. * Define a symbol like `std::__printf_stderr` which prints any message with any formatting to stderr, just as `std::printf` does to stdout, and call that from `std::__replacement_assert` instead of calling `__builtin_printf`. * Move `std::__replacement_assert` into libstdc++.so and no longer mark it as weak. This allows an application with some parts built against a previous libstdc++ to guarantee that the fix will be applied at least to the parts that are built against a libstdc++ containing the fix. libstdc++-v3/ChangeLog: include/bits/c++config (__glibcxx_assert): print to stderr. --- libstdc++-v3/include/bits/c++config | 8 ++++-- libstdc++-v3/src/c++98/Makefile.am | 1 + libstdc++-v3/src/c++98/Makefile.in | 2 +- libstdc++-v3/src/c++98/stdio.cc | 39 +++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 libstdc++-v3/src/c++98/stdio.cc diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index a64958096718126a49e8767694e913ed96108df2..d821ba09d88dc3e42ff1807200cfece71cc18bd9 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -523,6 +523,10 @@ namespace std # ifdef _GLIBCXX_VERBOSE_ASSERT namespace std { + // Avoid the use of stderr, because we're trying to keep the <cstdio> + // include out of the mix. + extern "C++" void* __stderr() _GLIBCXX_NOEXCEPT; + // Avoid the use of assert, because we're trying to keep the <cassert> // include out of the mix. extern "C++" _GLIBCXX_NORETURN @@ -531,8 +535,8 @@ namespace std const char* __function, const char* __condition) _GLIBCXX_NOEXCEPT { - __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, __line, - __function, __condition); + __builtin_fprintf(__stderr(), "%s:%d: %s: Assertion '%s' failed.\n", + __file, __line, __function, __condition); __builtin_abort(); } } diff --git a/libstdc++-v3/src/c++98/Makefile.am b/libstdc++-v3/src/c++98/Makefile.am index b48b57a2945780bb48496d3b5e76de4be61f836e..4032f914ea20344f51f2f219c5575d2a3858c44c 100644 --- a/libstdc++-v3/src/c++98/Makefile.am +++ b/libstdc++-v3/src/c++98/Makefile.am @@ -136,6 +136,7 @@ sources = \ math_stubs_float.cc \ math_stubs_long_double.cc \ stdexcept.cc \ + stdio.cc \ strstream.cc \ tree.cc \ istream.cc \ diff --git a/libstdc++-v3/src/c++98/Makefile.in b/libstdc++-v3/src/c++98/Makefile.in index f9ebb0ff4f4cb86cde7070b5ba6b8bf6a20515b3..e8aeb37d864a0ab7711d763fe8fbd3045db6e00d 100644 --- a/libstdc++-v3/src/c++98/Makefile.in +++ b/libstdc++-v3/src/c++98/Makefile.in @@ -142,7 +142,7 @@ am__objects_7 = bitmap_allocator.lo pool_allocator.lo mt_allocator.lo \ list.lo list-aux.lo list-aux-2.lo list_associated.lo \ list_associated-2.lo locale.lo locale_init.lo locale_facets.lo \ localename.lo math_stubs_float.lo math_stubs_long_double.lo \ - stdexcept.lo strstream.lo tree.lo istream.lo istream-string.lo \ + stdexcept.lo stdio.lo strstream.lo tree.lo istream.lo istream-string.lo \ streambuf.lo valarray.lo $(am__objects_1) $(am__objects_3) \ $(am__objects_6) am_libc__98convenience_la_OBJECTS = $(am__objects_7) diff --git a/libstdc++-v3/src/c++98/stdio.cc b/libstdc++-v3/src/c++98/stdio.cc new file mode 100644 index 0000000000000000000000000000000000000000..d0acb9117e1728f66f1a72ae3a9f471af72034ef --- /dev/null +++ b/libstdc++-v3/src/c++98/stdio.cc @@ -0,0 +1,39 @@ +// Portability symbols for <cstdio> -*- C++ -*- + +// Copyright (C) 2021-2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This 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 General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#include <bits/c++config.h> +#include <cstdio> + +namespace std { + +// The name stderr is specified to be a macro and is specified to be defined in +// C++ header cstdio or, equivalently, C header stdio.h. That means it cannot be +// used by code which intentionally avoids library includes, in particular, by +// bits/c++config. And it cannot be declared or even aliased in such headers +// since that would not be portable across libc implementations. +extern "C++" void* __stderr() _GLIBCXX_NOEXCEPT { + return stderr; +} + +} -- 2.30.2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] print extended assertion failures to stderr 2021-10-27 8:25 Jay Feldblum @ 2021-11-04 11:30 ` Jonathan Wakely 2021-11-04 23:44 ` Jonathan Wakely 0 siblings, 1 reply; 7+ messages in thread From: Jonathan Wakely @ 2021-11-04 11:30 UTC (permalink / raw) To: Jay Feldblum; +Cc: libstdc++, gcc Patches [-- Attachment #1: Type: text/plain, Size: 4480 bytes --] On Wed, 27 Oct 2021 at 09:27, Jay Feldblum via Libstdc++ < libstdc++@gcc.gnu.org> wrote: > From: yfeldblum <yfeldblum@gmail.com> > > The stdout stream is reserved for output intentionally produced by the > application. Assertion failures and other forms of logging must be > emitted to stderr, not to stdout. > > It is common for testing and monitoring infrastructure to scan stderr > for errors, such as for assertion failures, and to collect or retain > them for analysis or observation. It is a norm that assertion failures > match this expectation in practice. > > While `__builtin_fprintf` is available as a builtin, there is no > equivalent builtin for `stderr`. The only option in practice is to use > the macro `stderr`, which requires `#include <cstdio>`. It is desired > not to add such an include to `bits/c++config` so the solution is to > write and export a function which may be called by `bits/c++config`. > > This is expected to be API-compatible and ABI-compatible with caveats. > Code compiled against an earlier libstdc++ will work when linked into a > later libstdc++ but the stream to which assertion failures are logged is > anybody's guess, and in practice will be determined by the link line and > the choice of linker. This fix targets builds for which all C++ code is > built against a libstdc++ with the fix. > Thanks for the patch! Comments below. > > Alternatives: > * This, which is the smallest change. > * This, but also defining symbols `std::__stdin` and `std::__stdout` for > completeness. > * Define a symbol like `std::__printf_stderr` which prints any message > with any formatting to stderr, just as `std::printf` does to stdout, > and call that from `std::__replacement_assert` instead of calling > `__builtin_printf`. > * Move `std::__replacement_assert` into libstdc++.so and no longer mark > it as weak. This allows an application with some parts built against a > previous libstdc++ to guarantee that the fix will be applied at least > to the parts that are built against a libstdc++ containing the fix. > > libstdc++-v3/ChangeLog: > include/bits/c++config (__glibcxx_assert): print to stderr. > --- > libstdc++-v3/include/bits/c++config | 8 ++++-- > libstdc++-v3/src/c++98/Makefile.am | 1 + > libstdc++-v3/src/c++98/Makefile.in | 2 +- > libstdc++-v3/src/c++98/stdio.cc | 39 +++++++++++++++++++++++++++++ > 4 files changed, 47 insertions(+), 3 deletions(-) > create mode 100644 libstdc++-v3/src/c++98/stdio.cc > > diff --git a/libstdc++-v3/include/bits/c++config > b/libstdc++-v3/include/bits/c++config > index > a64958096718126a49e8767694e913ed96108df2..d821ba09d88dc3e42ff1807200cfece71cc18bd9 > 100644 > --- a/libstdc++-v3/include/bits/c++config > +++ b/libstdc++-v3/include/bits/c++config > @@ -523,6 +523,10 @@ namespace std > # ifdef _GLIBCXX_VERBOSE_ASSERT > namespace std > { > + // Avoid the use of stderr, because we're trying to keep the <cstdio> > + // include out of the mix. > + extern "C++" void* __stderr() _GLIBCXX_NOEXCEPT; > We can declare this locally in __replacement_assert, so it isn't made visible in namespace std. + > // Avoid the use of assert, because we're trying to keep the <cassert> > // include out of the mix. > extern "C++" _GLIBCXX_NORETURN > @@ -531,8 +535,8 @@ namespace std > const char* __function, const char* __condition) > _GLIBCXX_NOEXCEPT > { > - __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, > __line, > - __function, __condition); > + __builtin_fprintf(__stderr(), "%s:%d: %s: Assertion '%s' failed.\n", > + __file, __line, __function, __condition); > __builtin_abort(); > } > } > diff --git a/libstdc++-v3/src/c++98/Makefile.am > b/libstdc++-v3/src/c++98/Makefile.am > index > b48b57a2945780bb48496d3b5e76de4be61f836e..4032f914ea20344f51f2f219c5575d2a3858c44c > 100644 > --- a/libstdc++-v3/src/c++98/Makefile.am > +++ b/libstdc++-v3/src/c++98/Makefile.am > @@ -136,6 +136,7 @@ sources = \ > math_stubs_float.cc \ > math_stubs_long_double.cc \ > stdexcept.cc \ > + stdio.cc \ > I think adding it to src/c++11/debug.cc makes sense. That file already uses stderr itself, and is where we define other utilities for printing assertions. We also need to add it to the linker script, so that the symbol gets exported from the shared library. Otherwise any use of -D_GLIBCXX_ASSERTIONS or -D_GLIBCXX_DEBUG results in linker errors. The attached patch does that. [-- Attachment #2: patch.txt --] [-- Type: text/plain, Size: 4599 bytes --] commit 75e7612437f65abe21689845b1856bb308c6cb81 Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Nov 3 16:06:29 2021 libstdc++: Print assertion messages to stderr [PR59675] This replaces the printf used by failed debug assertions with fprintf, so we can write to stderr. To avoid including <stdio.h> we call a new function exported from the library, which returns the stderr pointer. libstdc++-v3/ChangeLog: PR libstdc++/59675 * acinclude.m4 (libtool_VERSION): Bump version. * config/abi/pre/gnu.ver (GLIBCXX_3.4.30): Add version and export new symbol. * configure: Regenerate. * include/bits/c++config (__replacement_assert): Use fprintf and write to stderr. * src/c++11/debug.cc (std::__stderr): Define. * testsuite/util/testsuite_abi.cc: Update latest version. diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 90ecc4a87a2..30a4abb98b3 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -3798,7 +3798,7 @@ changequote([,])dnl fi # For libtool versioning info, format is CURRENT:REVISION:AGE -libtool_VERSION=6:29:0 +libtool_VERSION=6:30:0 # Everything parsed; figure out what files and settings to use. case $enable_symvers in diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 5323c7f0604..3c59465ab9e 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2397,6 +2397,12 @@ GLIBCXX_3.4.29 { } GLIBCXX_3.4.28; +GLIBCXX_3.4.30 { + + _ZSt8__stderrv; + +} GLIBCXX_3.4.29; + # Symbols in the support library (libsupc++) have their own tag. CXXABI_1.3 { diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index c1aea827070..7dc7dcee029 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -74892,7 +74892,7 @@ $as_echo "$as_me: WARNING: === Symbol versioning will be disabled." >&2;} fi # For libtool versioning info, format is CURRENT:REVISION:AGE -libtool_VERSION=6:29:0 +libtool_VERSION=6:30:0 # Everything parsed; figure out what files and settings to use. case $enable_symvers in diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index a6495809671..75421731cae 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -531,8 +531,10 @@ namespace std const char* __function, const char* __condition) _GLIBCXX_NOEXCEPT { - __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, __line, - __function, __condition); + // Also avoid including <cstdio>. + extern void* __stderr() _GLIBCXX_NOEXCEPT; + __builtin_fprintf(__stderr(), "%s:%d: %s: Assertion '%s' failed.\n", + __file, __line, __function, __condition); __builtin_abort(); } } diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index 0128535135e..e79e49ea439 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -43,6 +43,12 @@ #include "mutex_pool.h" +namespace std +{ + // Used by std::__replacement_assert in <bits/c++config.h>. + void* __stderr() noexcept { return stderr; } +} + using namespace std; namespace @@ -1202,4 +1208,5 @@ namespace __gnu_debug const char*) const; #endif + } // namespace __gnu_debug diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc index 3af5dc593c2..1ca7da4fcd0 100644 --- a/libstdc++-v3/testsuite/util/testsuite_abi.cc +++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc @@ -210,6 +210,7 @@ check_version(symbol& test, bool added) known_versions.push_back("GLIBCXX_3.4.27"); known_versions.push_back("GLIBCXX_3.4.28"); known_versions.push_back("GLIBCXX_3.4.29"); + known_versions.push_back("GLIBCXX_3.4.30"); known_versions.push_back("GLIBCXX_LDBL_3.4.29"); known_versions.push_back("GLIBCXX_IEEE128_3.4.29"); known_versions.push_back("CXXABI_1.3"); @@ -245,7 +246,7 @@ check_version(symbol& test, bool added) test.version_status = symbol::incompatible; // Check that added symbols are added in the latest pre-release version. - bool latestp = (test.version_name == "GLIBCXX_3.4.29" + bool latestp = (test.version_name == "GLIBCXX_3.4.30" // XXX remove next 3 lines when baselines have been regenerated // to include {IEEE128,LDBL} symbols: || test.version_name == "GLIBCXX_LDBL_3.4.29" ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] print extended assertion failures to stderr 2021-11-04 11:30 ` Jonathan Wakely @ 2021-11-04 23:44 ` Jonathan Wakely 0 siblings, 0 replies; 7+ messages in thread From: Jonathan Wakely @ 2021-11-04 23:44 UTC (permalink / raw) To: Jay Feldblum; +Cc: libstdc++, gcc Patches On Thu, 4 Nov 2021 at 11:30, Jonathan Wakely <jwakely@redhat.com> wrote: > > > On Wed, 27 Oct 2021 at 09:27, Jay Feldblum via Libstdc++ < > libstdc++@gcc.gnu.org> wrote: > >> From: yfeldblum <yfeldblum@gmail.com> >> >> The stdout stream is reserved for output intentionally produced by the >> application. Assertion failures and other forms of logging must be >> emitted to stderr, not to stdout. >> >> It is common for testing and monitoring infrastructure to scan stderr >> for errors, such as for assertion failures, and to collect or retain >> them for analysis or observation. It is a norm that assertion failures >> match this expectation in practice. >> >> While `__builtin_fprintf` is available as a builtin, there is no >> equivalent builtin for `stderr`. The only option in practice is to use >> the macro `stderr`, which requires `#include <cstdio>`. It is desired >> not to add such an include to `bits/c++config` so the solution is to >> write and export a function which may be called by `bits/c++config`. >> >> This is expected to be API-compatible and ABI-compatible with caveats. >> Code compiled against an earlier libstdc++ will work when linked into a >> later libstdc++ but the stream to which assertion failures are logged is >> anybody's guess, and in practice will be determined by the link line and >> the choice of linker. This fix targets builds for which all C++ code is >> built against a libstdc++ with the fix. >> > > Thanks for the patch! Comments below. > > > >> >> Alternatives: >> * This, which is the smallest change. >> * This, but also defining symbols `std::__stdin` and `std::__stdout` for >> completeness. >> * Define a symbol like `std::__printf_stderr` which prints any message >> with any formatting to stderr, just as `std::printf` does to stdout, >> and call that from `std::__replacement_assert` instead of calling >> `__builtin_printf`. >> * Move `std::__replacement_assert` into libstdc++.so and no longer mark >> it as weak. This allows an application with some parts built against a >> previous libstdc++ to guarantee that the fix will be applied at least >> to the parts that are built against a libstdc++ containing the fix. >> > Actually it wouldn't guarantee it even for the new parts. Any objects built against the old libstdc++ headers might contain a definition of std::__replacement_assert, and that would get used in preference to the one in libstdc++.so, even for the new objects built against the new headers. To make it work we could change the signature of the function (e.g. use long or unsigned instead of int for the line number) so that code compiled against the new headers look for a new symbol, and never use one in old objects. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-11-04 23:44 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-11-04 13:53 [PATCH] print extended assertion failures to stderr sotrdg sotrdg 2021-11-04 13:54 ` Jonathan Wakely [not found] ` <CH2PR02MB65229EA7D6AA4BCC9515F087B28D9@CH2PR02MB6522.namprd02.prod.outlook.com> [not found] ` <CACb0b4m7oddSaVMqDG61gDQ_++pC4nrJYRpPE3U6E+QRbyVNQA@mail.gmail.com> 2021-11-04 14:17 ` sotrdg sotrdg 2021-11-04 15:13 ` Jonathan Wakely -- strict thread matches above, loose matches on Subject: below -- 2021-10-27 8:25 Jay Feldblum 2021-11-04 11:30 ` Jonathan Wakely 2021-11-04 23:44 ` Jonathan Wakely
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).