[Ruby] sleep(): stack level too deep (SystemStackError)

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Gamebuster
  • Registratie: Juli 2007
  • Laatst online: 15-09 23:08
Ik heb een eigen ThreadPool gemaakt waarin ik in mijn code om een of andere voor mij erg vage rede met enige regelmaat de volgende error krijgt:

code:
1
thread_pool.rb:44: stack level too deep (SystemStackError)


De code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
require "thread"
require "./color_out.rb"

Thread.abort_on_exception = true

class ThreadPool
    
    def initialize(limit)
        @queue = []
        @queue_mutex = Mutex.new
        @threads = []
        @threads_running = 0
        limit.times do @threads << (Thread.new do
                begin
                    runnable = get_from_queue
                    if runnable.nil?
                        sleep 0.1
                        next
                    end
                    @threads_running += 1
                    begin
                        runnable[:prc].call *runnable[:args]
                    rescue => e
                        ColorOut.puts_red "IN THREADPOOL: <#{e.class}> #{e.message}\r\n#{e.backtrace.join "\r\n"}"
                    end
                    @threads_running -= 1
                end while true
            end)
        end
    end

    def add_to_queue(*args, &block)
        @queue_mutex.synchronize do
            @queue << { :args => args, :prc => Proc.new(&block) }
        end
    end

    def threads
        @threads
    end
    
    def join
        begin
            sleep 0.1
        rescue => e
            ColorOut.puts_red "ThreadPool#join: <#{e.class}> #{e.message}"
            retry
        end while queue_length > 0 || @threads_running > 0
    end

    def queue_length
        @queue.length
    end

    def get_from_queue
        runnable = nil
        @queue_mutex.synchronize do
            runnable = @queue.shift
        end
        
        runnable
    end

end


Het vreemde is dat de error niet gevangen wordt door het begin rescue end blok.

Nog vreemder is dat ik de fout niet kan reproduceren in testcode en ik helaas de omliggende code niet kan delen.

Mijn vraag is dan ook: In welke gevallen kan de sleep-method een "stack level too deep" error geven? Wat zou de oorzaak kunnen zijn? Is er een manier om een stacktrace te krijgen bij die error? Ik heb 'm nog niet weten te "vangen" met een rescue-blok

AFAIK is stack-level-too-deep alleen van toepassing bij recursieve functies, en sleep is AFAIK geen recursieve functie.

edit:
Na lang puzzelen en sterk veranderen van mijn thread_pool krijg ik opeens deze:
/gems/mechanize-2.0.1/lib/mechanize/form.rb:187: stack level too deep (SystemStackError)

... opnieuw geen backtrace, wel zelfde error.

Waarschijnlijk zit de error gewoon daarin, maar kan-ie op een of andere manier niet "gevangen" ("rescue") worden en krijg ik die error pas bij sleep

[ Voor 10% gewijzigd door Gamebuster op 07-09-2011 21:59 ]

Let op: Mijn post bevat meningen, aannames of onwaarheden


Acties:
  • 0 Henk 'm!

  • Bigs
  • Registratie: Mei 2000
  • Niet online
Volgens mij is Mechanize niet thread safe.. dat kan natuurlijk voor allerlei vage problemen zorgen.

Acties:
  • 0 Henk 'm!

  • Gamebuster
  • Registratie: Juli 2007
  • Laatst online: 15-09 23:08
Bug opgelost:

1 van de websites die Mechanize bezocht gaf een redirect met een URL zonder hostname. Daar ging mijn software niet juist mee om, waardoor-ie uiteindelijk eindeloos de request herhaalde en uiteindelijk doodliep.

Het lag dus totaal niet aan mijn multi-threading. Dat Mechanize niet thread-safe zou zijn is niet relevant, want mechanize-instances worden niet gedeeld tussen threads; iedere thread heeft zijn eigen Mechanize.

Let op: Mijn post bevat meningen, aannames of onwaarheden