Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > SystemStackError: stack level too deep

Reply
Thread Tools

SystemStackError: stack level too deep

 
 
Oliver Peng
Guest
Posts: n/a
 
      02-29-2008
Now I am writing a server code to handle each connection by forking a
new process. Here is the code:

@tcpServer = TCPServer.new(host, port)

while true
if tcp = @tcpServer.accept
fork do
// handle all request in this connection
end
tcp && tcp.close
end
end

@tcpServer.close_read
@tcpServer.close_write

I also set up trap to handle CLD signal:
trap("CLD") {
pid_info_array = Process.waitall
}

After a period of time, I got the error:

SystemStackError: stack level too deep

The position is at the line of Process.waitall.

I have tried to use Process.wait, but this problem still exist.

Any ideas. Thanks.
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Robert Klemme
Guest
Posts: n/a
 
      03-01-2008
On 29.02.2008 22:15, Oliver Peng wrote:
> Now I am writing a server code to handle each connection by forking a
> new process. Here is the code:
>
> @tcpServer = TCPServer.new(host, port)
>
> while true
> if tcp = @tcpServer.accept
> fork do
> // handle all request in this connection
> end
> tcp && tcp.close
> end
> end
>
> @tcpServer.close_read
> @tcpServer.close_write
>
> I also set up trap to handle CLD signal:
> trap("CLD") {
> pid_info_array = Process.waitall
> }
>
> After a period of time, I got the error:
>
> SystemStackError: stack level too deep
>
> The position is at the line of Process.waitall.
>
> I have tried to use Process.wait, but this problem still exist.
>
> Any ideas. Thanks.


You are doing an unhealthy mix: Process.waitall and wait block to wait
for an event but SIGCLD is supposed to be called when that event happens.

So either, use Process.waitall in main or change the trap code to do
something like manipulating a child process counter so you can detect
when the last is gone.

But at the heart of your problem is a logic error: you cannot have an
endless loop and wait for all children to exit at the same time. Either
you decide in the main loop that now no more children are to be created
OR you just have a main loop that runs forever - but then there is no
point in waiting for all childs to terminate.

Kind regards

robert
 
Reply With Quote
 
 
 
 
Oliver Peng
Guest
Posts: n/a
 
      03-03-2008
Robert Klemme wrote:
> On 29.02.2008 22:15, Oliver Peng wrote:
>> tcp && tcp.close
>>
>> After a period of time, I got the error:
>>
>> SystemStackError: stack level too deep
>>
>> The position is at the line of Process.waitall.
>>
>> I have tried to use Process.wait, but this problem still exist.
>>
>> Any ideas. Thanks.

>
> But at the heart of your problem is a logic error: you cannot have an
> endless loop and wait for all children to exit at the same time. Either
> you decide in the main loop that now no more children are to be created
> OR you just have a main loop that runs forever - but then there is no
> point in waiting for all childs to terminate.
>
> Kind regards
>
> robert

Hi Robert:

Thanks for your replay.

> You are doing an unhealthy mix: Process.waitall and wait block to wait
> for an event but SIGCLD is supposed to be called when that event
> happens.
>
> So either, use Process.waitall in main or change the trap code to do
> something like manipulating a child process counter so you can detect
> when the last is gone.
>

Sorry. I am not sure what do you mean. In my code, it trap the CLD
signal to run wait method to clean the zombie sub-process, which is same
as the sample code in book 'Programming ruby'.

When a child process dies, a signal, SIGCHLD (or SIGCLD) is sent to its
parent process. So when I run Process.wait, I always should get the
response at once. And this code can work. The only problem is sometimes
SystemStackError was raised.

Can you please use sample code to show me where is the problem?

Thanks.



--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      03-03-2008
2008/3/3, Oliver Peng <(E-Mail Removed)>:
> Robert Klemme wrote:


> > You are doing an unhealthy mix: Process.waitall and wait block to wait
> > for an event but SIGCLD is supposed to be called when that event
> > happens.
> >
> > So either, use Process.waitall in main or change the trap code to do
> > something like manipulating a child process counter so you can detect
> > when the last is gone.

>
> Sorry. I am not sure what do you mean. In my code, it trap the CLD
> signal to run wait method to clean the zombie sub-process, which is same
> as the sample code in book 'Programming ruby'.


There is no trace of Process.waitall in the signal handler sample code.

> When a child process dies, a signal, SIGCHLD (or SIGCLD) is sent to its
> parent process. So when I run Process.wait, I always should get the
> response at once. And this code can work. The only problem is sometimes
> SystemStackError was raised.
>
> Can you please use sample code to show me where is the problem?


The problem is in waitall. The sample code otherwise works ok. Try this

trap "CLD" do
puts "#{Process.wait} exited"
# alternative
p Process.wait2
end

5.times do |i|
pid = fork do
puts "proc #{i}"
end and puts "#{pid} created"
end

puts "all children created"

sleep 10

Here's another approach

require 'pp'

5.times do |i|
pid = fork do
puts "proc #{i}"
end and puts "#{pid} created"
end

puts "all children created"

pp Process.waitall


Kind regards

robert

--
use.inject do |as, often| as.you_can - without end

 
Reply With Quote
 
Oliver Peng
Guest
Posts: n/a
 
      03-03-2008
Robert Klemme wrote:
> 2008/3/3, Oliver Peng <(E-Mail Removed)>:
>> Robert Klemme wrote:

>
>> as the sample code in book 'Programming ruby'.

> There is no trace of Process.waitall in the signal handler sample code.
>
>> When a child process dies, a signal, SIGCHLD (or SIGCLD) is sent to its
>> parent process. So when I run Process.wait, I always should get the
>> response at once. And this code can work. The only problem is sometimes
>> SystemStackError was raised.
>>
>> Can you please use sample code to show me where is the problem?

>
> The problem is in waitall. The sample code otherwise works ok. Try
> this
>
> trap "CLD" do
> puts "#{Process.wait} exited"
> # alternative
> p Process.wait2
> end
>
> 5.times do |i|
> pid = fork do
> puts "proc #{i}"
> end and puts "#{pid} created"
> end
>
> puts "all children created"
>
> sleep 10
>
> Here's another approach
>
> require 'pp'
>
> 5.times do |i|
> pid = fork do
> puts "proc #{i}"
> end and puts "#{pid} created"
> end
>
> puts "all children created"
>
> pp Process.waitall
>
>
> Kind regards
>
> robert


Ok. I see. You mean that waitall shouldn't be used in trap 'CLD' because
it would wait until all process exit.

But I use wait at first and get the SystemStackError exception. Then I
try to use waitall later. So I still don't know why the SystemStackError
exception is raised.

I also try to write test code and please have a look:

----------------------------------------------------
Server code:
require 'socket'

trap('CLD') do
pid = Process.wait
puts "pid #{pid} exited"
end

class TestServer

def initialize
@tcpServer = TCPServer.new('0.0.0.0', 7777)
end

def run
while tcp = @tcpServer.accept
fork do
begin
while str = tcp.gets()
tcp.puts("hello")
end
ensure
tcp.close_read
tcp.close_write
end
end
tcp.close
end
end
end

server = TestServer.new

server.run

------------------------------------------------
Client code:

require 'socket'

threads = []
100.times do
threads << Thread.new() do
while true
socket = TCPSocket.new('localhost', 7777)
socket.puts("hello")
sleep 1
socket.gets
socket.close
sleep 10
end
end
end

threads.each {|thr| thr.join}

From the server output, I can see that CLD signal has been traped and
server puts the process exit. But from top I can see that zombie process
are getting more and more. Is there some problem in the code logic?

Thanks.
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Robert Klemme
Guest
Posts: n/a
 
      03-05-2008
On 03.03.2008 21:54, Oliver Peng wrote:
> Robert Klemme wrote:
>> 2008/3/3, Oliver Peng <(E-Mail Removed)>:
>>> Robert Klemme wrote:
>>> as the sample code in book 'Programming ruby'.

>> There is no trace of Process.waitall in the signal handler sample code.
>>
>>> When a child process dies, a signal, SIGCHLD (or SIGCLD) is sent to its
>>> parent process. So when I run Process.wait, I always should get the
>>> response at once. And this code can work. The only problem is sometimes
>>> SystemStackError was raised.
>>>
>>> Can you please use sample code to show me where is the problem?

>> The problem is in waitall. The sample code otherwise works ok. Try
>> this
>>
>> trap "CLD" do
>> puts "#{Process.wait} exited"
>> # alternative
>> p Process.wait2
>> end
>>
>> 5.times do |i|
>> pid = fork do
>> puts "proc #{i}"
>> end and puts "#{pid} created"
>> end
>>
>> puts "all children created"
>>
>> sleep 10
>>
>> Here's another approach
>>
>> require 'pp'
>>
>> 5.times do |i|
>> pid = fork do
>> puts "proc #{i}"
>> end and puts "#{pid} created"
>> end
>>
>> puts "all children created"
>>
>> pp Process.waitall
>>
>>
>> Kind regards
>>
>> robert

>
> Ok. I see. You mean that waitall shouldn't be used in trap 'CLD' because
> it would wait until all process exit.
>
> But I use wait at first and get the SystemStackError exception. Then I
> try to use waitall later. So I still don't know why the SystemStackError
> exception is raised.
>
> I also try to write test code and please have a look:
>
> ----------------------------------------------------
> Server code:
> require 'socket'
>
> trap('CLD') do
> pid = Process.wait
> puts "pid #{pid} exited"
> end
>
> class TestServer
>
> def initialize
> @tcpServer = TCPServer.new('0.0.0.0', 7777)
> end
>
> def run
> while tcp = @tcpServer.accept
> fork do
> begin
> while str = tcp.gets()
> tcp.puts("hello")
> end
> ensure
> tcp.close_read
> tcp.close_write
> end
> end
> tcp.close
> end
> end
> end
>
> server = TestServer.new
>
> server.run
>
> ------------------------------------------------
> Client code:
>
> require 'socket'
>
> threads = []
> 100.times do
> threads << Thread.new() do
> while true
> socket = TCPSocket.new('localhost', 7777)
> socket.puts("hello")
> sleep 1
> socket.gets
> socket.close
> sleep 10
> end
> end
> end
>
> threads.each {|thr| thr.join}
>
> From the server output, I can see that CLD signal has been traped and
> server puts the process exit. But from top I can see that zombie process
> are getting more and more. Is there some problem in the code logic?


I can't really see one. Can you post the exception with the stack trace?

Kind regards

robert
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
"stack level too deep"... because Threads keep their "starting" stack Sam Roberts Ruby 1 02-11-2005 04:25 AM
[Q] YAML Error: stack level too deep E.-R. Bruecklmeier Ruby 4 07-06-2004 08:19 PM
yaml, level too deep, stack error Jean-Hugues ROBERT Ruby 1 04-27-2004 02:58 PM
Stack level too deep (SystemStackError) Jesper Olsen Ruby 7 01-16-2004 12:19 PM
stack level too deep on ia64 Eric Schwartz Ruby 3 11-11-2003 06:00 PM



Advertisments