bug#27532: getprogname: support for qemu

2017-06-29 Thread Jim Meyering
On Thu, Jun 29, 2017 at 9:50 AM, Assaf Gordon  wrote:
> Hello Bruno and all,
>
>> On Jun 29, 2017, at 12:26, Bruno Haible  wrote:
>>
...
> Luckily, many GNU test scripts already use "$prog" perl variable
> for the program's name in error message, so perhaps it would be possible
> to accomodate qemu without code changes.
>
> I've encountered the same for my program (datamash).
> and as an ugly hack added an undocumented option to print the program's name
> to set '$prog' accordingly:
> https://git.savannah.gnu.org/cgit/datamash.git/tree/tests/datamash-tests.pl#n37
>   ## Cross-Compiling portability hack:
>   ##  under qemu/binfmt, argv[0] (which is used to report errors) will contain
>   ##  the full path of the binary, if the binary is on the $PATH.
>   ##  So we try to detect what is the actual returned value of the program
>   ##  in case of an error.
>   my $prog = `$prog_bin ---print-progname`;
>   $prog = $prog_bin unless $prog;
>
>
> But this hack can be avoided, if we just run 'grep' with invalid
> arguments, triggering an error, then extracting the program name from STDERR.
>
> E.g. for 
> https://git.savannah.gnu.org/cgit/grep.git/tree/tests/filename-lineno.pl
> change the following on line 26 from:
> my $prog = 'grep';
> to
> my $prog = 'grep';
> my $full_prog_name = `$prog --invalid-option-for-testing 2>&1 | head -n1 
> | cut -f1 -d:`;
> $prog = $full_prog_name if $full_prog_name;
>
> This is untested code, but should work more-or-less.
> Once "$prog" is updated, all the tests should pass.

Thanks to both of you.
Does this patch solve the problem?
From d86483b0c4be5298c96ccaaa62670a04b018af42 Mon Sep 17 00:00:00 2001
From: Jim Meyering 
Date: Thu, 29 Jun 2017 18:06:11 -0700
Subject: [PATCH] tests: avoid false failure when run in qemu user mode

* tests/filename-lineno.pl: Derive the program name that grep
will use in diagnostics, based on a suggestion from Assaf Gordon.
Reported by Bruno Haible in http://bugs.gnu.org/27532
---
 tests/filename-lineno.pl | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tests/filename-lineno.pl b/tests/filename-lineno.pl
index 8eead57..6cc86b7 100755
--- a/tests/filename-lineno.pl
+++ b/tests/filename-lineno.pl
@@ -24,6 +24,9 @@ use strict;
 (my $program_name = $0) =~ s|.*/||;

 my $prog = 'grep';
+my $full_prog_name = `$prog --no-such-option 2>&1`;
+$full_prog_name =~ s/:.*//s;
+$prog = $full_prog_name if $full_prog_name;

 # Turn off localization of executable's output.
 @ENV{qw(LANGUAGE LANG LC_ALL)} = ('C') x 3;
-- 
2.13.0



bug#27532: getprogname: support for qemu

2017-06-29 Thread Assaf Gordon
Hello Bruno and all,

> On Jun 29, 2017, at 12:26, Bruno Haible  wrote:
> 
> When running the testsuite of grep-3.0 with qemu user mode, some tests fail.
> [...]
> *** 1 
> ! grep: g:4: Unmatched [...
> --- 1 
> ! /tmp/grep-3.0/build-arm64/src/grep: g:4: Unmatched [...
> [...]
> argv[0] = absolute file name of qemu-aarch64
> argv[1] = absolute file name of grep (it must be absolute, since it's not
>   qemu's job to search for 'grep' in $PATH).

Luckily, many GNU test scripts already use "$prog" perl variable
for the program's name in error message, so perhaps it would be possible
to accomodate qemu without code changes.

I've encountered the same for my program (datamash).
and as an ugly hack added an undocumented option to print the program's name
to set '$prog' accordingly:
https://git.savannah.gnu.org/cgit/datamash.git/tree/tests/datamash-tests.pl#n37
  ## Cross-Compiling portability hack:
  ##  under qemu/binfmt, argv[0] (which is used to report errors) will contain
  ##  the full path of the binary, if the binary is on the $PATH.
  ##  So we try to detect what is the actual returned value of the program
  ##  in case of an error.
  my $prog = `$prog_bin ---print-progname`;
  $prog = $prog_bin unless $prog;


But this hack can be avoided, if we just run 'grep' with invalid
arguments, triggering an error, then extracting the program name from STDERR.

E.g. for 
https://git.savannah.gnu.org/cgit/grep.git/tree/tests/filename-lineno.pl
change the following on line 26 from:
my $prog = 'grep';
to
my $prog = 'grep';
my $full_prog_name = `$prog --invalid-option-for-testing 2>&1 | head -n1 | 
cut -f1 -d:`;
$prog = $full_prog_name if $full_prog_name;

This is untested code, but should work more-or-less.
Once "$prog" is updated, all the tests should pass.

Hope this helps,
regards,
 - assaf










bug#27532: grep test failures under qemu

2017-06-29 Thread Bruno Haible
Oops, the title was wrong.
Corrected subject: "grep test failures under qemu"






bug#27532: getprogname: support for qemu

2017-06-29 Thread Bruno Haible
Hi,

When running the testsuite of grep-3.0 with qemu user mode, some tests fail.

How to reproduce:
- On a Debian or Ubuntu system, install package 'g++-5-aarch64-linux-gnu'.
- Install qemu-2.8.1 or qemu-2.9.0 from source.
- Prepare for executing aarch64 binaries:
  $ sudo update-binfmts --install qemu-aarch64 
$HOME/inst-qemu/2.8.1/bin/qemu-aarch64 --magic 
'\x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00'
 --mask 
'\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
 --offset 0 --credential no
  $ QEMU_LD_PREFIX=/usr/aarch64-linux-gnu; export QEMU_LD_PREFIX
- $ ../configure --host=aarch64-linux CC="aarch64-linux-gnu-gcc-5"
- $ make
- $ make check

Test failure example:
filename-lineno.pl: test invalid-re: stderr mismatch, comparing invalid-re.1 
(expected) and invalid-re.E (actual)
*** invalid-re.1Thu Jun 29 17:40:54 2017
--- invalid-re.EThu Jun 29 17:40:54 2017
***
*** 1 
! grep: g:4: Unmatched [...
--- 1 
! /tmp/grep-3.0/build-arm64/src/grep: g:4: Unmatched [...

How come? The test suite invokes 'grep' from $PATH but:
1) When the x86_64 kernel is about to execute a native aarch64 binary, it
   prepares an argv with
 argv[0] = absolute file name of qemu-aarch64
 argv[1] = absolute file name of grep (it must be absolute, since it's not
   qemu's job to search for 'grep' in $PATH).
2) Inside grep, which is linked to glibc, the error() function used is the one
   from glibc. The one from gnulib, present in grep's source code, is not
   compiled. The error() function in glibc uses program_invocation_name,
   which is the absolute path of 'grep' by (1).
   The error() function in glibc does *not* use program_invocation_short_name,
   nor does it use gnulib's getprogname() which would also return
   program_invocation_short_name.

The following proof-of-concept patch fixes the problem - "make check" passes -,
but I don't know whether
  - you want something like this at all,
  - you want to limit it to the test situation. i.e. make the behaviour depend
on some environment variable,
  - you prefer to fix the test suite instead (by removing the dirname of the
program from the output before comparison with the expected result).

Bruno


--- grep-3.0/src/grep.c.bak 2017-02-09 02:37:33.0 +0100
+++ grep-3.0/src/grep.c 2017-06-29 18:07:53.072178500 +0200
@@ -2432,6 +2432,15 @@
   return result;
 }
 
+#if __GLIBC__ >= 2
+extern void (*error_print_progname) (void);
+static void
+error_print_program_invocation_short_name (void)
+{
+  fprintf (stderr, "%s: ", program_invocation_short_name);
+}
+#endif
+
 int
 main (int argc, char **argv)
 {
@@ -2445,6 +2454,10 @@
   int fread_errno;
   intmax_t default_context;
   FILE *fp;
+
+#if __GLIBC__ >= 2
+  error_print_progname = error_print_program_invocation_short_name;
+#endif
   exit_failure = EXIT_TROUBLE;
   initialize_main (&argc, &argv);