bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Named fifo's causing hanging bash scripts


From: werner
Subject: Named fifo's causing hanging bash scripts
Date: Mon, 12 Jan 2015 15:55:00 +0100 (CET)

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc -I/home/abuild/rpmbuild/BUILD/bash-4.3 
-L/home/abuild/rpmbuild/BUILD/bash-4.3/../readline-6.3
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-suse-linux-gnu' 
-DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib   -fmessage-length=0 
-grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector 
-funwind-tables -fasynchronous-unwind-tables -g  -D_GNU_SOURCE -DRECYCLES_PIDS 
-Wall -g -Wuninitialized -Wextra -Wno-unprototyped-calls -Wno-switch-enum 
-Wno-unused-variable -Wno-unused-parameter -Wno-parentheses -ftree-loop-linear 
-pipe -DBNC382214=0 -DMUST_UNBLOCK_CHLD=1 -DIMPORT_FUNCTIONS_DEF=0 -fprofile-use
uname output: Linux d136 3.15.0-rc7-3-desktop #1 SMP PREEMPT Wed May 28 
15:39:51 UTC 2014 (96f5b60) x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-suse-linux-gnu

Bash Version: 4.3
Patch Level: 33
Release Status: release

Description:
        Named fifo's causing hanging bash scripts like

        while IFS="|" read a b c ; do
          [shell code]
        done < <(shell code)

        can cause random hangs of the bash.    An strace shows that the bash
        stays in wait4()

Repeat-By:
        Here is a script which had been modified to do no real work but show
        the problem:

#!/bin/bash

# Task: go through the files in $RPM_BUILD_ROOT and
# relink symbolic links so that:
# links crossing top level directory boundaries (/usr/* -> /etc/*)
#   are absolute links
# links below one top level directory (/usr/bin/* -> /usr/lib/*)
#   are relative links
# NOTE: we're not doing this to fix a problem (as no matter how you
#   do it you fix one problem by creating another). We're doing it
#   so we can document this as policy - so you can rely on it

# Additional Task: check some usual errors arround symlinks e.g.
#   dangling symlinks or symlinks to init scripts in wrong location

# Author: Stephan Kulow <address@hidden>
#
# major speedup: Tomas Cech <address@hidden> and Michal Kubecek <address@hidden>

# If using normal root, avoid changing anything.
###if [ -z "$RPM_BUILD_ROOT" ]; then
###     exit 0
###fi
RPM_BUILD_ROOT=/

strip_slashes() {
    local loc="${!1}"
    local tmp="${loc//\/\///}"
    while [ "$loc" != "$tmp" ]; do
        loc="$tmp"
        tmp="${loc//\/\///}"
    done
    eval "$1"="'$loc'"
}

eat_component() {
    loc="${!1}"
    local rslt="${loc#/*/}"
    if [ "$rslt" != "$loc" ]; then
        rslt="/$rslt"
    else
        rslt="${loc##/*}"
    fi
    eval "$1"="'$rslt'"
}

top_dir () {
    local rslt
    if [ "${1:0:1}" = / ]; then
        rslt="${1:1}"
        rslt="/${rslt%%/*}"
    else
        rslt="$1"
    fi
    eval "$2"="'$rslt'"
}

LC_ALL=
LANG=
LC_TIME=POSIX

basename_int() {
    echo "${1##*/}"
}

dirname_int() {
    local rslt="${1%/*}"
    if [ -n "$rslt" ]; then
        echo "$rslt"
    elif [ "${1:0:1}" = / ]; then
        echo /
    else
        echo .
    fi
}

cd $RPM_BUILD_ROOT

had_errors=0

while IFS="|" read link link_dir link_dest
do
    link="${link#.}"
    link_dir="${link_dir#.}"
    orig_link_dest="$link_dest"

    new_link_dest=NONE
    link_dir="$(dirname_int $link)"

    case $link_dest in
        .|..|../..) # link to current dir
          continue ;;
        .*) # relative links up
          link_dest="$link_dir/$link_dest"
          ;;
        /*) # absolute links
          ;;
        */*) # relative links down
          link_dest="$link_dir/$link_dest"
          ;;
        *) # the rest
          continue
    esac

    # cleaning out double slash
    strip_slashes link_dest
    link_dest="${link_dest%.}"
    link_dest="${link_dest%/}"

    # eliminating /./ components
    link_dest="${link_dest//\/.\///}"

    counter=0
    # eliminating back references
    while [[ $link_dest =~ /\.\. ]]; do
       link_dest="$(sed "s@/[^/]\+/\.\.@@" <<< "$link_dest")"
       case $link_dest in
        /..*) # this is very mean
            echo "ERROR: $link points to illegal $link_dest"
            exit 1
            ;;
        esac
        counter=$((counter + 1))
        if test $counter -gt 10; then
            echo "ERROR: more than 10 back references in $link?"
            exit 1
        fi
    done

    if test "$link" = "$link_dest"; then
      echo "ERROR: $link points to itself (as $orig_link_dest)"
      exit 1
    fi

    # black list
    case "$link,$link_dest" in
        *,/var/lib/named*)
            continue;;
        /usr/etc,*|/usr/tmp,*)
            continue;;
        */share/texmf/*|/usr/share/terminfo/*)
             continue;;
        /sbin/init,*) # don't create absolute symlink for /sbin/init
             continue;;
        *,/etc/alternatives/*) # white list alternatives
             ;;
        *share/automake-*)
             echo "ERROR: link target $link points into automake directory"
             echo " You might want to add a -c to the automake call (or just"
             echo " skip the files from packaging)"
             exit 1
             ;;
        *,/opt/kde3/share/doc*/HTML/*/common) # white listed for not existant
             ;;
        *,/usr/share/doc/kde/HTML/*/common) # white listed for not existant
             ;;
        *,/proc/*) # links pointing into /proc file system
             ;;
        *)
          if test ! -L ./$link_dest && test ! -e $link_dest && test ! -e 
./$link_dest; then
            echo "ERROR: link target doesn't exist (neither in build root nor 
in installed system):"
            echo "  $link -> $link_dest"
            echo "Add the package providing the target to neededforbuild and 
Requires"
            test "$NO_BRP_STALE_LINK_ERROR" != "yes" && had_errors=1
          fi
          ;;
    esac

    forced_absolute=0
    for prefix in /usr/X11R6/lib/X11 /usr/X11R6/include/X11 
/usr/X11R6/lib/X11/app-defaults ; do
      if [[ $link =~ ^$prefix/ ]]; then
         if ! [[ $link_dest =~ ^$prefix/ ]]; then
            # not ok
            forced_absolute=1
         fi
      fi
    done

    dest_dir="$(dirname_int $link_dest)"

    # figuring out (currently) correct destination
    if [ "$link_dir" = "$dest_dir" -o  "$dest_dir" = "." ]; then
        new_link_dest="$(basename_int $link_dest)"
    else
        # figuring out top level directory
        top_dir "$link" top_link
        top_dir "$link_dest" top_dest
        if [ "$forced_absolute" = 0 -a "$top_link" = "$top_dest" ]; then # 
supposed to be relative

            # first we need to cut out the common prefix
            link_tmp=$link
            while [ "$top_link" = "$top_dest" ]; do
                link_orig=$link_tmp
                dest_orig=$link_dest
                link_tmp="/${link_tmp#/*/}"
                link_dest="/${link_dest#/*/}"
                top_link="${link_tmp#/}"
                top_link="/${top_link%%/*}"
                top_dest="${link_dest#/}"
                top_dest="/${top_dest%%/*}"

                if [ "$top_dest" = "$dest_orig" -o "$top_link" = "$link_orig" 
]; then
                    link_tmp="$link_orig"
                    link_dest="$dest_orig"
                    break
                fi
            done

            # now we add a .. for every directory component
            link_tmp="$(dirname_int $link_tmp)"

            if [ "$link_tmp" = "$link_dest" ]; then
                new_link_dest=.
            elif [ "$link_tmp" != "/" ]; then # we have a directory component
                link_rel=

                while [ -n "$link_tmp" ]; do
                    eat_component link_tmp
                    link_rel="../$link_rel"
                done

                new_link_dest="$link_rel/$link_dest"
                strip_slashes new_link_dest

            else
                # get rid of the slash
                link_dest="${link_dest#/}"
                new_link_dest="$link_dest"
            fi
        else
            new_link_dest="$link_dest"
        fi
    fi

    if [ "$new_link_dest" != NONE -a "$new_link_dest" != "$orig_link_dest" ]; 
then
        echo "INFO: relinking $link -> $new_link_dest (was $orig_link_dest)"
        ### rm ./$link && ln -s $new_link_dest ./$link
    fi
done < <(find . -type l -printf '%p|%h|%l\n' 2>/dev/null)

if test "$had_errors" = 1; then
    exit 1
fi



reply via email to

[Prev in Thread] Current Thread [Next in Thread]