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.
You have a stack overflow.
Your
getlinefunction callsprepline, which callsadvance, which callsgetline.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.)