2014-12-04 14 views
9

Attualmente stiamo aggiornando la nostra app per Rails su Rails 4. In 3.2, i nostri test di Cucumber (1.3.17) funzionano bene (se lentamente), con Capybara (2.4.4), Poltergeist (1.5.1) e PhantomJS (1.9.8) sotto il cofano.I test di cetriolo falliscono con `stream closed (IOError)`

Ma in entrambi 4.0.12 e 4.1.8, otteniamo una stream closed (IOError) in un punto casuale nella corsa:

stream closed (IOError) 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/formatter/pretty.rb:156:in `write' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/formatter/pretty.rb:156:in `puts' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/formatter/pretty.rb:156:in `step_name' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:181:in `block in send_to_all' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:179:in `each' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:179:in `send_to_all' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:173:in `broadcast' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:119:in `visit_step_name' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:112:in `block in visit_step_result' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:170:in `broadcast' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:111:in `visit_step_result' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/step_invocation.rb:43:in `visit_step_result' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/step_invocation.rb:39:in `accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:106:in `block in visit_step' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:170:in `broadcast' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:105:in `visit_step' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/step_collection.rb:19:in `block in accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/step_collection.rb:18:in `each' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/step_collection.rb:18:in `accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:100:in `block in visit_steps' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:170:in `broadcast' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:99:in `visit_steps' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:15:in `block in execute' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime.rb:83:in `block (2 levels) in with_hooks' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime.rb:99:in `before_and_after' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime.rb:82:in `block in with_hooks' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime/support_code.rb:120:in `call' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime/support_code.rb:120:in `block (3 levels) in around' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/language_support/language_methods.rb:9:in `block in around' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/language_support/language_methods.rb:97:in `call' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/language_support/language_methods.rb:97:in `execute_around' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/language_support/language_methods.rb:8:in `around' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime/support_code.rb:119:in `block (2 levels) in around' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime/support_code.rb:123:in `call' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime/support_code.rb:123:in `around' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime.rb:94:in `around' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime.rb:81:in `with_hooks' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:13:in `execute' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/scenario.rb:32:in `block in accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/scenario.rb:79:in `with_visitor' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/scenario.rb:31:in `accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:58:in `block in visit_feature_element' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:170:in `broadcast' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:57:in `visit_feature_element' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/feature.rb:38:in `block in accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/feature.rb:37:in `each' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/feature.rb:37:in `accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:27:in `block in visit_feature' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:170:in `broadcast' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:26:in `visit_feature' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/features.rb:28:in `block in accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/features.rb:17:in `each' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/features.rb:17:in `each' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/features.rb:27:in `accept' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:21:in `block in visit_features' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:170:in `broadcast' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/ast/tree_walker.rb:20:in `visit_features' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/runtime.rb:49:in `run!' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/lib/cucumber/cli/main.rb:47:in `execute!' 
/var/lib/jenkins/.rvm/gems/[email protected]/gems/cucumber-1.3.17/bin/cucumber:13:in `' 
/var/lib/jenkins/.rvm/gems/[email protected]/bin/cucumber:23:in `load' 
/var/lib/jenkins/.rvm/gems/[email protected]/bin/cucumber:23:in `' 
/var/lib/jenkins/.rvm/gems/[email protected]/bin/ruby_executable_hooks:15:in `eval' 
/var/lib/jenkins/.rvm/gems/[email protected]/bin/ruby_executable_hooks:15:in `' 

Questo errore è not the same come un errore closed stream, il che significa che si sta tentando toccare un flusso dopo che è stato chiuso.

No, l'unica volta che uno stream closed (IOError) viene lanciato in tutta la risonanza magnetica è in rb_thread_fd_close. Il codice a sua volta viene chiamato solo in rb_io_close, ovvero quando si chiude un descrittore di file; itera attraverso gli altri thread live e vede se qualcuno di essi sta aspettando il descrittore di file chiuso. Se c'è qualcuno in attesa, solleva l'errore stream closed nel thread in attesa. Questo spiega chiaramente perché la traccia dello stack punta al cetriolo: questo è il thread che attende di scrivere su STDOUT, dal formattatore. Ma non abbiamo alcuna informazione su chi ha chiuso il descrittore di file.

Poiché so che mi sto occupando di thread qui, inizio a suspect timeout uccidere qualcosa quando non dovrebbe essere, ma non ho modo di sapere che cosa sta causando il pasticcio timeout; Ho rimosso quello nel mio codice, ma ho trovato 35 in varie gemme che stiamo usando, e il problema si sta ancora verificando.

Abbiamo anche sospettato, ad un certo punto, che uno dei processi phantomjs veniva ucciso a causa di poca memoria, e abbiamo aggiunto la strumentazione per puts il processo di memoria corrente prima di ogni scenario ... e le IOError s andati via, quasi certamente a causa di problemi di temporizzazione. Quando ho rimosso la strumentazione, gli errori sono tornati.

Ho anche tentato di aggiornare il cetriolo della punta di alberi e il capibara, ma nessuno dei due sembrava fare la differenza.

C'è qualche modo intelligente per rintracciare ciò che non ho ancora provato? Hai visto questo problema e conosci il cambio di configurazione di una riga, ho bisogno di renderlo migliore? Hai una comoda patch che rimuove timeout da tutto il Ruby ovunque?

+0

Stai testando una macchina virtuale in cui i file host si trovano sul sistema operativo principale e vengono condivisi con la VM tramite NFS/qualsiasi altra cosa? Ho ricevuto errori del genere ed è a causa dei ritardi del file system introdotti con questi mezzi. – JakeTheSnake

+0

@JakeTheSnake no, è una VM ma i file sono ospitati sul disco virtuale. – TALlama

risposta

1

idee da provare ...

  • stretto il problema provando Capybara + WebKit; Poltergeist non è thread-safe (AFAIK).

  • stretto il problema di vedere se si tratta di un timeout rack:

    # config/initializers/timeout.rb 
    Rack::Timeout.timeout = 600 
    Rack::Timeout.wait_timeout = 600 # or 0 means never timeout 
    
  • temporaneamente disattivare qualsiasi test che chiamano per esterni, come il sistema, sidekiq, eventmachine, lavoro in ritardo, etc.

  • Per la vostra idea di una patch che rimuove timeout da tutto Rubino ovunque:

    require 'timeout' 
    Thread.handle_interrupt(TimeoutError => :never) { 
        timeout(10){ 
        # TimeoutError doesn't occur here 
        Thread.handle_interrupt(TimeoutError => :on_blocking) { 
         # possible to be killed by TimeoutError 
         # while blocking operation 
        } 
        # TimeoutError doesn't occur here 
        } 
    } 
    

    Vedi Guarding from Timeout Error

  • traccia gli oggetti file aprire in ogni punti di interruzione che si desidera:

    # List all open File objects. 
    ObjectSpace.each_object(File) do |f| 
        puts "%s: %d" % [f.path, f.fileno] unless f.closed? 
    end 
    
    # List the "dangling" File object which we didn't store in a variable. 
    ObjectSpace.each_object(File) do |f| 
        unless f.closed? 
        printf "%s: %d\n", f.path, f.fileno unless f === filehandle 
        end 
    end 
    

    Vedi Where does Ruby keep track of its open file descriptors

0

prova questo:

Nel codice dopo aver aperto il file per la lettura è necessario chiuderlo. See this similar issue

+0

Se avessi la minima idea di quali file sarebbero stati lasciati aperti sarebbe facile, ma l'errore non fornisce alcun indizio. Non sono nemmeno sicuro che sia io a lasciare i file aperti; potrebbe essere un file temporaneo da una gemma. Probabilmente sono io, perché questo errore è troppo difficile da trovare online perché questo sia un problema di prosciutto, ma non ho modo di saperlo. – TALlama

Problemi correlati