Hello --

While trying to debug an offsite-backup script, I found an odd bug
in GNU tar related to the LANG environment variable:  if LANG isn't
set when I use tar to create a compressed archive, tar fails silently.
That is, it doesn't write the archive and it exits with code 141
without any other indication that there was an error.  (A session
recording and version info are below.)

I tracked this down to the code in sys_child_open_for_compress()
after the fork() that creates the child (gzip) process, but before
the child runs exec() of gzip.  Within this span, the child receives
SIGSEGV, then the parent receives SIGPIPE when it tries to write
data to the child.

The SIGSEGV is caused by the call to gettext() (via the macro "_")
at line 347 of system.c:

    set_program_name (_("tar (child)"));

The same failure happens when untarring a compressed archive,
although it's not a silent failure in that case.  (See sample
session, below.)  That happens at the corresponding point in
sys_child_open_for_uncompress().

I don't know whether there's a bug in gettext(), or a bug in the
way gettext() is used here.  I built a test-version of tar that
omits the call to gettext(), passing the string directly to
set_program_name(), and it behaves normally.

I've worked around the problem by defining LANG in my offsite-backup
script, so fixing this problem isn't urgent.  Let me know if you
need more info or if I can help by running other tests.

Thanks.

Jeremy Scofield
jlscofi...@mac.com
Seattle

========================== Details Follow ==========================

VERSIONS
    Mac OS X 10.11.3 (El Capitan)
    GNU tar 1.28 (Built by the Macports facility.  The only patches
        to the released sources seem to be in supporting Apple's
        extended attributes.)

OTHER RANDOM OBSERVATIONS

    If I move the gettext() call to a spot before the fork(), there's
    no SIGSEGV.  The forking appears to be necessary.

    If I add another identical call to gettext() in a spot before
    the fork(), there's no SIGSEGV at either call.  Somehow a call
    before the fork() makes the later call safe.  Maybe some kind
    of caching in gettext()?

    The version of GNU tar that I extracted from an old backup
    (1.17) doesn't exhibit this problem.

SAMPLE SESSION (with comments added)

    $ ls                                # tar is GNU 1.28, otar is GNU 1.17,
                                        # ttar is GNU 1.28 with my test change
    otar                testdir         typescript
    tar                 ttar

    $ echo $LANG
    en_US.ISO8859-1
    $ tar -cz -f 1.tgz testdir          # This works as expected
    $ ls
    1.tgz               tar             ttar
    otar                testdir         typescript

    $ tar -t -f 1.tgz                   # Ditto for untar
    testdir/
    testdir/misc.c
    testdir/system.c
    testdir/xattrs.c

    $ unset LANG
    $ tar -cz -f 2.tgz testdir          # This is the silent failure
    $ echo $?
    141                                 # exit code 141
    $ ls                                # archive wasn't created
    1.tgz               tar             ttar
    otar                testdir         typescript

    $ tar -t -f 1.tgz                   # Similar problem with untar
    tar: Child died with signal 11      # but it's not silent
    tar: Error is not recoverable: exiting now

    $ ttar -cz -f 3.tgz testdir         # Test version without call to gettext
    $ echo $?                           # exit code 0, archive created
    0
    $ ls
    1.tgz               otar            testdir         typescript
    3.tgz               tar             ttar

    $ ttar -t -f 1.tgz                  # untar also works
    testdir/
    testdir/misc.c
    testdir/system.c
    testdir/xattrs.c

================================ End ================================

Reply via email to