Forum: Ruby Got SystemStackError exception: stack level too deep

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
9d5ecfdd21d16e79e14aa1800ae095d9?d=identicon&s=25 Bezan Kapadia (bezan)
on 2009-02-10 00:13
I have master Process that is forking 2 child processes in the
background.

Now one of the child process is sending a mail out to me using the smtp
server every minute.

After about 20 hours I get the following error below:
 Got Timeout::Error exception: execution expired
 Got SystemExit exception: exit

Am guessing the above error is to with the slow server Network.
The program continues fine because I have trapped the exception using
"rescue".

After about 6 hours I get the following:
Got SystemStackError exception: stack level too deep

Once I get this error my entire program begins to bomb and work
incorrectly.

Can someone explain what does this error really mean "Got
SystemStackError exception: stack level too deep" ?
and if there are anything to look for or keep in mind to contain or
prevent this error or some kind of work around etc...?

Thanks in advance
2f55791ab9018b4d01fb741fab21843d?d=identicon&s=25 Tony Arcieri (Guest)
on 2009-02-10 00:39
(Received via mailing list)
On Mon, Feb 9, 2009 at 4:12 PM, Bezan Kapadia <bezan99@gmail.com> wrote:

> Can someone explain what does this error really mean "Got
> SystemStackError exception: stack level too deep" ?
> and if there are anything to look for or keep in mind to contain or
> prevent this error or some kind of work around etc...?
>

It means that you have too many calls to functions which are in turn
calling
other functions before returning.  A quick and easy way to cause a
similar
error is:

 def foo; foo; end
 foo

The stack trace you get with the SystemStackError will be enormously
helpful
in diagnosing this problem.  Perhaps you can paste it to the list?
9d5ecfdd21d16e79e14aa1800ae095d9?d=identicon&s=25 Bezan Kapadia (bezan)
on 2009-02-10 01:29
I see ...

My code below : The function 1 calls the function mail_system every 60
seconds.

Take a look at my 2 functions below and can u suggest of what should I
really change to do away with this issue

require 'net/smtp'

def mail_system(message,i)

user=`echo $USER`.chomp
recipient=user+"@gmail.com"
msg = "#{message}"
Net::SMTP.start('smtp.gmail.com',25) do |smtp|
smtp.send_message(msg, "#{recipient}", "#{recipient}")
Notification for Email Sent completion - #{message}"
end
rescue Timeout::Error => e
$mes_trace.error("Got #{e.class} exception: #{e.message}")
puts "Got #{e.class} exception: #{e.message}"
exit false
end



def function1
........
mail_system(message,i)
rescue Exception => e
    $mes_trace.error("Got #{e.class} exception: #{e.message}")
    puts "Got #{e.class} exception: #{e.message}"
end

sleep(60)
end






Tony Arcieri wrote:
> On Mon, Feb 9, 2009 at 4:12 PM, Bezan Kapadia <bezan99@gmail.com> wrote:
>
>> Can someone explain what does this error really mean "Got
>> SystemStackError exception: stack level too deep" ?
>> and if there are anything to look for or keep in mind to contain or
>> prevent this error or some kind of work around etc...?
>>
>
> It means that you have too many calls to functions which are in turn
> calling
> other functions before returning.  A quick and easy way to cause a
> similar
> error is:
>
>  def foo; foo; end
>  foo
>
> The stack trace you get with the SystemStackError will be enormously
> helpful
> in diagnosing this problem.  Perhaps you can paste it to the list?
3d61a8dbbd64d0feed8698689cf15276?d=identicon&s=25 Jayce Meade (Guest)
on 2009-02-10 01:47
(Received via mailing list)
Notification for Email Sent completion - #{message}"
end

It looks to me like you have an " to terminate a string but you don’t
have
one to begin it. Because of that, It's probably encountering the word
'for'
and interpreting it as a loop construct and it just goes over and over
and
over since there's nothing to break the loop. My guess is that the root
of
the stack level error is in the code being taken as part of the loop...

Maybe I missed it, if so, I apologize, but that's what it looks like to
me.
Hope it helps.

  - jayce

--------------------------------------------------
From: "Bezan Kapadia" <bezan99@gmail.com>
Sent: Monday, February 09, 2009 4:28 PM
Newsgroups: comp.lang.ruby
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Subject: Re: Got SystemStackError exception: stack level too deep
9d5ecfdd21d16e79e14aa1800ae095d9?d=identicon&s=25 Bezan Kapadia (bezan)
on 2009-02-10 01:58
ahh No ...thats the issue with my cut copy paste .. sorry I pasted that
incorrectly here..I have pasted that line correctly below..
puts "Notification for Email Sent completion - #{message}"


>>stack trace you get with the SystemStackError will be enormously helpful
Where do I get this from..?


Jayce Meade wrote:
> Notification for Email Sent completion - #{message}"
> end
>
> It looks to me like you have an " to terminate a string but you don’t
> have
> one to begin it. Because of that, It's probably encountering the word
> 'for'
> and interpreting it as a loop construct and it just goes over and over
> and
> over since there's nothing to break the loop. My guess is that the root
> of
> the stack level error is in the code being taken as part of the loop...
>
> Maybe I missed it, if so, I apologize, but that's what it looks like to
> me.
> Hope it helps.
>
>   - jayce
>
> --------------------------------------------------
> From: "Bezan Kapadia" <bezan99@gmail.com>
> Sent: Monday, February 09, 2009 4:28 PM
> Newsgroups: comp.lang.ruby
> To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
> Subject: Re: Got SystemStackError exception: stack level too deep
3d61a8dbbd64d0feed8698689cf15276?d=identicon&s=25 Jayce Meade (Guest)
on 2009-02-10 02:13
(Received via mailing list)
if this is all in a single file you should paste all of it. it seems
it's
missing some code and you should also paste the whole error.

 -jayce

--------------------------------------------------
From: "Bezan Kapadia" <bezan99@gmail.com>
Sent: Monday, February 09, 2009 4:57 PM
Newsgroups: comp.lang.ruby
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Subject: Re: Got SystemStackError exception: stack level too deep
9d5ecfdd21d16e79e14aa1800ae095d9?d=identicon&s=25 Bezan Kapadia (bezan)
on 2009-02-10 03:08
Well there are multiple Files and its complicated.. but I think the
issue definately lies some where in the part of the code that I have
pasted above.

The scripts have run days in the background and the error that I have
pasted is all that is there in the trace File.
3d61a8dbbd64d0feed8698689cf15276?d=identicon&s=25 Jayce Meade (Guest)
on 2009-02-10 03:19
(Received via mailing list)
Trace file? If you're sending attachments, I don't thing the mailing
list
allows them.

--------------------------------------------------
From: "Bezan Kapadia" <bezan99@gmail.com>
Sent: Monday, February 09, 2009 6:07 PM
Newsgroups: comp.lang.ruby
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Subject: Re: Got SystemStackError exception: stack level too deep
2f55791ab9018b4d01fb741fab21843d?d=identicon&s=25 Tony Arcieri (Guest)
on 2009-02-10 03:21
(Received via mailing list)
On Mon, Feb 9, 2009 at 7:07 PM, Bezan Kapadia <bezan99@gmail.com> wrote:

> The scripts have run days in the background and the error that I have
> pasted is all that is there in the trace File.
>

Can you provide the complete stack trace associated with the
SystemStackError?
3d61a8dbbd64d0feed8698689cf15276?d=identicon&s=25 Jayce Meade (Guest)
on 2009-02-10 03:47
(Received via mailing list)
Perhaps your error-checking code is causing the program to restart when
the
error crops up. If so, it might lead to the stack error. If say, every
six
hours, something changes (I think that's how long you said it took) and
it
causes an error, the original error is caught and the program
continues/restarts execution. If the error trapping code restarts by
calling
the methods used to start the script in the first place, it would turn
into
a stack error if it's not done correctly.

It would be like writing something on a piece of paper. Say once this
figurative piece of paper is full, the stack error crops up. If your
program
error is equivalent to the end of a line of text on this piece of paper,
after every error, or line, the program restarts, or a new line is
started.
The problem here is that as the errors or lines of text add up on this
piece
of paper, eventually, the paper is full, and you can't write anything
else
on it, and the StackError pops up.

Basically put, your program may be just writing line after line to this
piece of paper rather than starting with a clean sheet every time it
restarts. What you want to do is go all the way back up to the program's
initiation, where the first line of code used to start the program is,
and
set up your error rescuing code there, that way, the error is caught
where
the program begins, and you can safely restart it because that's where
the
program started in the first place.

This probably isn't even proper syntax, but bear with me:

def method1() # B
    #...
    rescue Exception # C
        # restarting code here
end

method1() # A

###

A is  the last line where method1 is called.
B is where method1 is defined/executed
C is where you have your error catching code

Right here, its basically doing this:

A -> B -> Error pops up -> Rescued by C in the context of B -> A -> B ->
Error - > rescued by C in the context of B -> A  and so on.

You want it to do this instead:

def method1 #B
    #...
end

begin
    method1() # A

rescue Exception #C
    #... Error catching code here, maybe output to console
    retry

end


this time, it's doing this:

A -> B -> Error pops up -> Rescued and restarted by C in top - level
context ->  Program restarts, executing line A in top-level context

In this one, instead of restarting in the context of B, it's going all
the
way back to the top level of execution and restarting from there, rather
than in the context of the program's execution code itself.

A good way to set up an error system so you know what happened and
where,
and specifically why it happened is to raise a runtime error like so and
then catch it later:

def method1
    # ...
    rescue Exception => e
        raise("Errored in method1: #{e}")
    end
end

begin
    method1()

rescue RuntimeError => e
    puts e
    # .. what to do next
end

Hope that all made sense! =P

  Hope it helps, too. From what I've learned you want to restart your
program from where it was started initially to avoid things building up
and
getting problematic.

 - jayce

--------------------------------------------------
From: "Jayce Meade" <azimuth-rubytalk@live.com>
Sent: Monday, February 09, 2009 6:17 PM
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Subject: Re: Got SystemStackError exception: stack level too deep
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-02-10 14:45
Bezan Kapadia wrote:
> rescue Timeout::Error => e
> $mes_trace.error("Got #{e.class} exception: #{e.message}")
> puts "Got #{e.class} exception: #{e.message}"

puts e.backtrace.join("\n")

This should give you the backtrace you need to understand what's
happening. (Although sometimes I think it can be garbled in the case of
a stack overflow error)
9d5ecfdd21d16e79e14aa1800ae095d9?d=identicon&s=25 Bezan Kapadia (bezan)
on 2009-02-15 21:57
Ok .. Well I tested the Code again.

This Time the code errored out after 40 hrs with only the System Stack
error.

Some things I have noted this time..
_________________________________________________
1)This is how my child process code that runs in the background looks
like -

The code is precisely doing what Tony has indicated above that could be
possibly triggering the Stack error exception.


#Main Program

def check_for_running_jobs
       begin

       # do a whole lot of work


       rescue Exception => e
      $mes_trace.error("In MES_monitor check_for_running_jobs : Got
#{e.class} exception: #{e.message}")
      puts "Got #{e.class} exception: #{e.message}"
      $mes_trace.error(e.backtrace.join("\n"))
      puts e.backtrace.join("\n")

  end

end


def run_function

#this function internally calls tons of XYZ functions...
check_for_running_jobs
# there are rescue statements in various of these XYZ functions to trap
exceptions....


sleep(60) #note it gets activated every 60 seconds

run_function
end

run_function

###################################
One thing I wanted to know that if I have an exception in some function
(run_function and if I rescue that exception in the function
(run_function or within other functions that this function calls)
...does that restart execution of the entire program again (note am not
doing anything like calling some other method or anything else except
rescuing the error)....leading to stack error..
_______________________________________________

2) Just a Side Note - Am trying to run this background child process for
days / may be even weeks something like a cron job that sleeps , wakes
up, polls the status and goes to sleep.

Is it robust way to Run a detached child process in the background for
weeks ...?
______________________________________________

3) Ok I have got hold of my backtrace if you folks want to take closer
look...

I, [06:12:05#22059]  INFO -- : Sleeping for 2 Minutes
I, [06:13:05#22059]  INFO -- : Finished Sleeping for 2 Minutes
E, [06:13:05#22059] ERROR -- : In MES_monitor check_for_running_jobs :
Got SystemStackError exception: stack level too deep
E, [06:13:05#22059] ERROR -- :
/usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/monitor.rb:273:in
`mon_check_owner'
/usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/monitor.rb:220:in `mon_exit'
/usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/monitor.rb:240:in `synchronize'
/usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/logger.rb:496:in `write'
/usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/logger.rb:326:in `add'
/usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/logger.rb:374:in `info'
./MES_monitor.rb:90:in `check_for_running_jobs'
./MES_monitor.rb:78:in `times'
./MES_monitor.rb:78:in `check_for_running_jobs'
./MES_monitor.rb:70:in `each'
./MES_monitor.rb:70:in `check_for_running_jobs'
./MES_monitor.rb:272:in `run_function'
./MES_monitor.rb:281:in `run_function'
./MES_monitor.rb:283

_________________________________________________

4)

Jayce from what you suggested ...
#Main program

def run_function

#this function internally calls tons of XYZ functions...
check_for_running_jobs
# there are rescue statements in various of these XYZ functions to trap
exceptions....

sleep(60) #note it gets activated every 60 seconds

run_function
end

begin
run_function

           rescue Exception => e
      $mes_trace.error("In MES_monitor check_for_running_jobs : Got
#{e.class} exception: #{e.message}")
      puts "Got #{e.class} exception: #{e.message}"
      $mes_trace.error(e.backtrace.join("\n"))
      puts e.backtrace.join("\n")


end



Am going to fire test run with  the above change...Hopefully this will
solve my problem ...
let me know if you folks suggest anything else....
__________________________________________
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-02-15 22:40
Bezan Kapadia wrote:
> 2) Just a Side Note - Am trying to run this background child process for
> days / may be even weeks something like a cron job that sleeps , wakes
> up, polls the status and goes to sleep.
>
> Is it robust way to Run a detached child process in the background for
> weeks ...?

Yes, I have written systems like that. They have been robust enough not
to need any sort of supervisor. (If you do want to use a supervisor,
something like 'monit' should do the job)

> 3) Ok I have got hold of my backtrace if you folks want to take closer
> look...
>
> I, [06:12:05#22059]  INFO -- : Sleeping for 2 Minutes
> I, [06:13:05#22059]  INFO -- : Finished Sleeping for 2 Minutes
> E, [06:13:05#22059] ERROR -- : In MES_monitor check_for_running_jobs :
> Got SystemStackError exception: stack level too deep
> E, [06:13:05#22059] ERROR -- :
> /usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/monitor.rb:273:in
> `mon_check_owner'
> /usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/monitor.rb:220:in `mon_exit'
> /usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/monitor.rb:240:in `synchronize'
> /usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/logger.rb:496:in `write'
> /usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/logger.rb:326:in `add'
> /usr/pkgs/ruby/1.8.5-p12/lib/ruby/1.8/logger.rb:374:in `info'

Two things strike me from this:

1. You're using a rather old version of Ruby

2. You're using thread primitives (monitor / synchronize) and there are
known problems with them in older versions of Ruby.

I'd strongly suggest you upgrade to ruby-1.8.6p287. (Or you could try
1.8.6p114, but I'm not sure if all the thread issues were resolved by
then).

As an alternative, there's a separate library called "fastthread" which
you could try installing under your old version of Ruby.

http://groups.google.com/group/ruby-talk-google/br...

But I'd strongly recommend going 1.8.6 instead.

Regards,

Brian.
9d5ecfdd21d16e79e14aa1800ae095d9?d=identicon&s=25 Bezan Kapadia (bezan)
on 2009-02-16 00:00
Thanks..
I can move to a newer version..
but I think am hitting the issue that Tony indicated above..

>>def foo;foo;end
foo


Am wondering what the work around to that is in the context of my
code...I'm trying what Jayce suggested and will move to newer version,
Lets see what happens...

Please continue to pour in your suggestions...
9d5ecfdd21d16e79e14aa1800ae095d9?d=identicon&s=25 Bezan Kapadia (bezan)
on 2009-02-16 07:21
Since it takes 40 hrs for the Real code to cause the System Stack Error
I tried all the above suggestions in the mean while on the code below
and none seem to worked..(i.e I used newer versions of Ruby, rescue
statements in the manner indicated above etc etc )...but the stack level
too deep error keeps coming back.

The issue that triggers the exception:
def foo;foo;end
foo

__________________________

So i have tried an alternative solution of a while loop which seems to
be working fine so far but lets see..

while (1)

foo

end

def foo

end
___________________________

But if anyone knows of a neat way to get around the issue that Tony
indicated please let me know ....
753dcb78b3a3651127665da4bed3c782?d=identicon&s=25 Brian Candler (candlerb)
on 2009-02-16 10:10
Bezan Kapadia wrote:
> Since it takes 40 hrs for the Real code to cause the System Stack Error
> I tried all the above suggestions in the mean while on the code below
> and none seem to worked..(i.e I used newer versions of Ruby, rescue
> statements in the manner indicated above etc etc )...but the stack level
> too deep error keeps coming back.
>
> The issue that triggers the exception:
> def foo;foo;end
> foo

Sorry I didn't notice this in your original post:

def run_function
  ...
  sleep(60) #note it gets activated every 60 seconds
  run_function
end

Yes, what you've got there is infinite recursion. Some languages will
optimise out this "tail recursion" into a flat loop, but Ruby doesn't;
it will burn stack until it runs out of memory.

So you need to write this as an explicit loop, e.g.

def run_function
  while true
    ...
    sleep(60)
  end
end

> So i have tried an alternative solution of a while loop which seems to
> be working fine so far but lets see..

OK, you got there before me :-)

> But if anyone knows of a neat way to get around the issue that Tony
> indicated please let me know ....

ruby 1.9 does have the ability to optimise tail recursion, but only if
you compile it with a special flag. So in Ruby, I'd say it's better to
write an infinite loop as a loop, rather than as recursion.

Regards,

Brian.
This topic is locked and can not be replied to.