1

I've run into a bit of a stumper while trying to get a shell script working. I am trying to make a script that reads a line from a database and format into a text file to be used with another piece of software. The script needs to loop around 50 million times (large database), and it does so just fine until 5,500 to 5,800 iterations, then it develops a segmentation fault.
I've tried to trace the error with strace (The last few lines are below), but I'm not really sure what I'm looking at.

clone(child_stack=0,flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,                      child_tidptr=0xb76f8728) = 17547
close(4)                                = 0
close(5)                                = 0
pipe([4, 5])                            = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,     child_tidptr=0xb76f8728) = 17548
close(3)                                = 0
close(5)                                = 0
pipe([3, 5])                            = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17549
close(4)                                = 0
close(5)                                = 0
pipe([4, 5])                            = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17550
close(3)                                = 0
close(5)                                = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17551
close(4)                                = 0
close(-1)                               = -1 EBADF (Bad file descriptor)
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17546
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17547
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17548
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17549
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17551
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17550
--- SIGCHLD (Child exited) @ 0 (0) ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17545
--- SIGCHLD (Child exited) @ 0 (0) ---
write(1, "OK!\n", 4OK!
)                    = 4
pipe([3, 4])                            = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,   child_tidptr=0xb76f8728) = 17552
close(4)                                = 0
read(3, "10632\n", 128)                 = 6
read(3, "", 128)                        = 0
close(3)                                = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17552
--- SIGCHLD (Child exited) @ 0 (0) ---
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,    child_tidptr=0xb76f8728) = 17553
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17553
--- SIGCHLD (Child exited) @ 0 (0) ---
write(1, "Preparing file 10632 of ", 24Preparing file 10632 of ) = 24
write(1, "51041073(7) ....", 1651041073(7) ....)        = 16
pipe([3, 4])                            = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,    child_tidptr=0xb76f8728) = 17554
close(4)                                = 0
read(3, "8\n", 128)                     = 2
read(3, "", 128)                        = 0
close(3)                                = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 17554
--- SIGCHLD (Child exited) @ 0 (0) ---
pipe([3, 4])                            = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb76f8728) = 17555
close(4)                                = 0
read(3, "", 128)                        = 0
close(3)                                = 0
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV}], 0, NULL) = 17555
--- SIGCHLD (Child exited) @ 0 (0) ---
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Segmentation fault

The script is below:

#!/bin/sh
#----VARS----
prefix="10.0.3.2/read/"
oprdir="/home/andrew/doc/read/"
throttle=0

#----------------
x=5000
advcount=0
count=`curl "$prefix""count.php" 2> /dev/null`

#----Funcs----
getline()
{
  #Run curl to get the line of text
  #TODO -n
  echo -n "Preparing file" $x "of "
  if [ $advcount -ge 25 ]
  then
    count=`curl "$prefix""count.php" 2> /dev/null`
    advcount=0
  fi
  echo -n $count"("$advcount")" "...."
  advcount=`expr $advcount + 1`

  line=`curl "$prefix""testfile-prep.php?x=$x" 2> /dev/null`
  if [ "$line" = "ERR ERROR: X OUTSIDE RECORDS." ]
  then
    echo "ERROR: X OUTSIDE DB... WAITING TO RETRY."
    sleep 60
    getline
  fi
  prepline
}

prepline()
{
  echo $line | sed 's/^[0-9]*\./\n./g' | sed 's/\([a-zA-Z]*\)\./\1\n./g'  | sed 's/\,/\n\,/g' | sed 's/(\(.*\)/(\n\1/g' | sed 's/\(.*\))/\1\n)/g' | sed 's/ /\n/g'> out-0-$x.dat
  echo "OK!"
  #cat out-$x.dat
  advance
}
advance()
{
  x=`expr $x + 1`
  sleep $throttle
  getline
}

cd "$oprdir"
getline

Sorry for the novelette of information, any help is appreciated.

2
  • "The script needs to loop around 50 million times" I have to say that this suggest to me that a compiled (or JIT virtual machine) implementation might be a good idea for this use case. Or can you show that it is IO bound as it is? Commented Dec 20, 2011 at 1:26
  • 1
    Your prepline function can gang the multiple sed commands into a single one using sed -e 'command1' -e 'command2' .... This probably has nothing to do with your crash, but it will reduce the process count quite a bit. Commented Dec 20, 2011 at 2:16

1 Answer 1

4

You have a stack overflow.

Your getline function calls prepline, which calls advance, which calls getline.

You should use a loop of some kind rather than having a function call itself in a non-exceptional condition. (The self-call in the error case is okay, you won't have 5,000 errors that overflow the stack.)

Sign up to request clarification or add additional context in comments.

2 Comments

'To iterate is human; to recurse, divine?' Clearly not in this case, at any rate; explicit iteration somewhere will fix the problem.
That seems to fix it. Not really sure why I went with the functions like I did. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.