CMD BATCH RECURSION exceeds STACK limits

Hello Gents,

Who could give me the issue or solution of the termination of a script that should loop till it stopped manually.

The script is monitoring servers with different commands and are being called internally in the batch.
If necessary i can upload it.

The script itself works great.

Regards,

Urfried Jr.
recursion.jpg
urfriedAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dave BaldwinFixer of ProblemsCommented:
Recursion normally means that the script calls itself until a terminating condition is reached.  See if you can make your script work without doing that.  Another problem that can occur is that the script may not be reusing space but allocating new memory on each pass which ends up using all available memory.
0
Gerwin Jansen, EE MVETopic Advisor Commented:
Do you want to detect that the monitoring script has exited? You can do this with another script that watches the process list for existence of your monitoring script, or just create a script that starts your monitoring script but not in the background so when it exits it can start the monitoring script again.
0
urfriedAuthor Commented:
Gonna test some more... Usually it takes about 3 hours before it terminates. So takes a while to test.
What i forgot to mention, is that i start the batch using runas command in different profile.
For safety i will login properly and test again without runas.

Any idea how to prevent the script for using free mem ?
I will have a close look at the use of mem.
0
Starting with Angular 5

Learn the essential features and functions of the popular JavaScript framework for building mobile, desktop and web applications.

urfriedAuthor Commented:
Starting the script again is possible, but is not the best solution of the problem.
Besides, i would like to understand why it happens.
0
Paul TomasiCommented:
Easypeasy

Use a  sentinel.

This has other advantages too -0 for example, you can prevent multiple instances of the same batch file running at the same time.

Here's how it works.

At the start of your batch file, it looks to see if a particular file, the sentinel file, is present or not. If it is not present, then the batch file will procede. The first thing the batch file does is create a sentinel file. Then the batch file continues - even looping if necessary. Somewhere in the batch file, you need to check that the sentinel file is STILL present, and if it isn't then exit either immediately or gracefully.

The reason the batch file needs to check for the presence of the sentinel file is because you have control of the sentinel file outside of the batch file. In other words, the sentinel file can be manually deleted, or deleted using another batch file.

So, here's an overview of how it works (in English language):

@echo off
IF sentinel file is present THEN EXIT
create sentinel file
:loop
  ::
  :: your commands go here
  ::
IF sentinel file is present GOTO :loop
:end

This is how it would look like in a batch file:

@echo off
if exist sentinel exit /b
copy /y nul sentinel >nul
:loop
  rem
  rem add your commands here. The following line is for example purposes
  dir
  rem
if exist sentinel goto loop
exit /b

while the batch file is running, open up antoher DOS box and (1) try to run another instance of the batch file - it won' run. and (2) now manually delete the sentinel file with: 'DEL SENTINEL' command, and the batch file (in the first DOS box) will grind to an end.
0
Gerwin Jansen, EE MVETopic Advisor Commented:
@paultomasi - nice solution, I use a similar method, I only call the file 'trigger' where it triggers running a batch file in case the trigger file is present. I combine it with scheduled jobs that create these trigger files.
0
urfriedAuthor Commented:
yy.. but this is not preventing the script from being terminated by exceeding the STACK limits.
I am looking at the solution to prevent that.
0
Paul TomasiCommented:
Running out of stack space is associated to bad program design. In batch files there is no way to directly manipulate the stack - nor allocate more memory.

A recursive program will indeed use the system's stack but I have never come across an occasion when I myself have run out of stack space. The exception to this is where there was a bug in the program logic.

It might help us understand why you are running out of stack space if you explain what it is you are attempting to do. It might be possible to do whatever you are doing using a different method - if need be, to create a disk file-based stack but this would seriously impede execution time.

Is it the batch program flow itself that's using up your stack or is it an executable? Or, is it your recursion that's the problem?

If you can show us some code we would be in a better position to advise you further.

If all you are doing is monitoring remote boxes then I don't see why you need to use recursion. Also, are you scheduling the monitoring process as a pass-through batch file or just continually looping within the same batch file?

Oh, and what monitoring tools are you using?

Let's see some code!!
0
Paul TomasiCommented:
Oops! I meant "usually" associated with....
0
Paul TomasiCommented:
Also, all recursive programs rely on a conditional statement which passes control back to the parent program. This is also true of the terminating condition.
0
Paul TomasiCommented:
Right! I'm off out for a few hours now so good luck!
0
urfriedAuthor Commented:
code is comming :)

The script IS the infra monitoring.
0
urfriedAuthor Commented:
Here is the script.
test-infoboard.txt
0
Bill PrewCommented:
Taking a fairly quick look at your script, I suspect you problems lie in the following two statements:

for /f "tokens=7" %%a in ('ping nl03%host% -n 1 -w 1500 ^|find "Received"') do (if "%%a" EQU "1," (echo %ok%) >>%info% else (echo %not%%not%& goto %next%) >>%info% )

Open in new window

and:

if exist "C:\scripts\monitoring\%host%.off" (echo ^<img src="inf2.png" height="20" width="20"^> & goto %next%) >>%info%

Open in new window

These exist in a couple of subroutines you call frequently (:BBhosts and :Ping) and exit the subroutine without the normal GOTO :EOF or EXIT /B method.  That may leave something accumulating on a call stack, but not sure.  It's certainly risky practice I would say to jump to other locations in the script from insode a CALLed routine though.

You might consider doing the jump upon return from the routine, rather than in it.

~bp
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
urfriedAuthor Commented:
Thanx for looking.

Would an outside call of external batch help ?
Easy to test.. it probably is a little bit slower... but in this case i don't care.



0
Bill PrewCommented:
Nothing that you can do in an external BAT that you couldn't do in an internal routine.

~bp
0
Gerwin Jansen, EE MVETopic Advisor Commented:
I agree with bill, think you have to move the 2 goto statements out of the 2 mentioned if statements, replacing them with goto :eof and putting the goto statements after the statements where call :ping and call :bbhosts are.
0
Bill PrewCommented:
It looks like your BAT file could be simplified a bit, but it would take a bit of time to sort it out.

~bp
0
urfriedAuthor Commented:
Good one... now i understand his point.
Gonna test.... Make take a while before i have some results... (may take 4 hours)
0
Paul TomasiCommented:
Blimey! Just looked at the code. Wow! So much improvements can be made here!

Got to dash out again though. Will look back later.

For example, where you've got the following lines:
set task=Backup-run & call :TASKS
set task=move S006 backup & call :TASKS
set task=move S008 backup & call :TASKS
set task=move S009 backup & call :TASKS
set task=move S013 backup & call :TASKS

Open in new window

You could just do the following:
call :TASKS "Backup-run"
call :TASKS "move S006 backup"
call :TASKS "move S008 backup"
call :TASKS "move S009 backup"
call :TASKS "move S013 backup"

Open in new window

Followed by:
:TASKS
  for /f "tokens=9 delims=," %%r in ('schtasks /s %host% /query /fo csv /v ^|findstr /L /C:"%~1"') do (
    (if %%r EQU "0" (echo %ok%) else (echo %not%))>>%info%
  )
goto :EOF

Open in new window

0
Qlemo"Batchelor", Developer and EE Topic AdvisorCommented:
Oh yes, a lot of optimization and simplification.
For example, I cannot see any usage of the   host-   var you set very often to 0 (set host-=0). (1) that looks suspicious (2) the var never changes (in the batch scope), and hence needs only to be set once.

Then
for /f "tokens=6" %%a in ('paping %host% -p *** -c 1 ^|find "Attempted"') do (if "%%a" EQU "1," (echo %ok%) >>%info% else (echo - %not%) >>%info% )

Open in new window

is repeated 10 times on successive lines - is that correct? If, you would be better of using a counting loop (FOR /L) for the 10 calls. Anyway, the FOR is better written as
(for /f "tokens=6" %%a in ('paping %host% -p *** -c 1 ^|find "Attempted"') do if "%%a" EQU "1," (echo %ok%) else (echo - %not%)) >>%info%

Open in new window

or
>> %info% (for /f "tokens=6" %%a in ('paping %host% -p *** -c 1 ^|find "Attempted"') do if "%%a" EQU "1," (echo %ok%) else (echo - %not%))

Open in new window

which is the same.

I agree to the last post of Paul, but would even go so far to use a FOR. Replacing
set task=SyncBackPro 1& 					call :TASKS
set task=SyncBackPro 2& 					call :TASKS
set task=SyncBackPro 3& 					call :TASKS
set task=SyncBackPro 4& 					call :TASKS
set task=SyncBackPro 5& 					call :TASKS
set task=SyncBackPro 6& 					call :TASKS
set task=SyncBackPro 7& 					call :TASKS
set task=SyncBackPro 8& 					call :TASKS

Open in new window

with
for /L %%T in (1, 1, 8) do call :TASKS "SyncBackPro %%T"

Open in new window

and
set task=move S006 backup& 					call :TASKS
set task=move S008 backup& 					call :TASKS
set task=move S009 backup& 					call :TASKS
set task=move S013 backup& 					call :TASKS

Open in new window

with
for %%H in (S006 S008 S009 S013) do call :TASKS "move %%H backup%

Open in new window

aso.

BTW, overly using parens can increase issues, in particular with FOR. some replacements are not taking place the way you would expect them to be, and they increase the risk of Stack Overflow messages. But I agree that the most suspicious culprit is the jump to a label out of parens or subroutines, without executing exit /b or goto :EOF.
0
urfriedAuthor Commented:
Thanx a lot guys. A lot of improvements again.
Replacing goto statement to :EOF is going to improve a lot.

Qlemo: it is a large batch where i removed or changed a lot of lines, echo's, passwords, usernames and variables to make it a bit more readable for you all.

I will definitely have a look at all the improvements.

Thanx for the help so far.
I'll let you guys no results asap.





0
Bill PrewCommented:
@urfried

I also wanted to ask, in your original post, the error message you showed was not a typical Windows error message, what is that tool or program that generated those error messages?

Teleplan Monitoring Infra
ir 16—12—2011 — 15:48:30,07
******  B A T C H    R E C U R S I O N exceeds STACK limits ******
Recursion Count=879, stack usage=90 percent
******          B A T C H PROCESSING IS A B O R T E D       ******
c :\Scripts\Monitoring>

Open in new window

~bp
0
urfriedAuthor Commented:
@billprew:

I guess it is generated by cmd.exe
Because the script was terminated each 4 hours... i started the scripted called from an cmd console.
Easy debug method.
0
urfriedAuthor Commented:
Guys, The script is still running since yesterday.
So removing the GOTO outside the called command solved the issue.

Now it is time to create better coding to optimize it.

Thanx for all the help.
Learned again :), (therefore i'll split points a bit)
0
Bill PrewCommented:
Ah, so it is, I guess it's good I haven't seen that much ;-).

I wrote this little test program:

@echo off
call :a
exit /b
:a
call :a
exit /b

Open in new window

and got this result fairly quickly when I ran it:

******  B A T C H   R E C U R S I O N  exceeds STACK limits ******
Recursion Count=703, Stack Usage=90 percent
******       B A T C H   PROCESSING IS   A B O R T E D      ******

Open in new window

~bp
0
Paul TomasiCommented:
bill...

you're clutching at straws on this one (or so it seems) and that's not like you (or so it seemed)...

yes, calling itself will obviously invoke a stack overflow although, what's interesting from the output is the 'Recursion Count' of 703... Now, increasing the stack capacity would might be helpful in some circumstances.

a better example might have been as follows:
:a
call :b

:b
call :a

Open in new window

which gives a recursion count of 1240 but then, there is no data pushed onto the stack.

i think it's safe to say we should avoid writing cyclic code and be careful when writing recursive code.

btw, even after a stack overflow condition occurs, errorlevel is still 0.
0
Bill PrewCommented:
@Paul,

My only intent was confirming that the original error message was indeed coming right from the Windows command processor, since the format of the error message looked a little atypical. Wasn't after anything more than that...

~bp
0
Paul TomasiCommented:
bill...

i know it's just you being thorough, so no, i wasn't implying 'anything more than that...'

btw, '...' must be catching! :)

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft DOS

From novice to tech pro — start learning today.