Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Ruby capture the syntax error in threads

I am trying to code up a two-threads client using ruby, one thread reads the data from a socket and print it out, the other thread reads local data and send it to remote server. The problem I found is that it looks like Ruby cannot capture errors within a thread, here is an example:

#! /usr/bin/ruby

Thread.new {
  loop {
    $stdout.puts "hi"
    abc.puts ef
    sleep 1
  }
}


loop {
  sleep 1
}

Obviously, outside the thread if I type abc.puts ef the code will never run since Ruby will report "undefined variable abc". However if it is within a thread, there is no error report. My question is, how to let Ruby capture errors like this? Or at least, report something is wrong within a thread?

like image 493
xis Avatar asked Aug 17 '13 18:08

xis


People also ask

What is thread safe in Ruby?

Multithreading is the ability to execute code on multiple concurrent threads. Each thread exists within a process, and each process can have at least one thread.

How do threads work in Ruby?

Thread in Ruby allows the developer to write codes where they can be able to write and execute many programs at once, in technical words suppose we are going to perform two operations addition and multiplication at the same time, it is not possible with normal way because it will execute either addition first or ...

Are Ruby hashes thread safe?

Unfortunately, Ruby doesn't ship with any thread-safe Array or Hash implementations. The core Array and Hash classes are not thread-safe by default, nor should they be.

How many threads can be executed at a time Ruby?

Only one thread may load or unload at a time, and to do either, it must wait until no other threads are running application code.


2 Answers

Use Thread::abort_on_exception=:

According to Thread - Exception Handling:

Any thread can raise an exception using the raise instance method, which operates similarly to Kernel#raise.

However, it's important to note that an exception that occurs in any thread except the main thread depends on abort_on_exception. This option is false by default, meaning that any unhandled exception will cause the thread to terminate silently when waited on by either join or value. You can change this default by either abort_on_exception= true or setting $DEBUG to true.

...

Thread::abort_on_exception = true
Thread.new {
  loop {
    $stdout.puts "hi"
    abc.puts ef
    sleep 1
  }
}


loop {
  sleep 1
}

=>

hi
t.rb:5:in `block (2 levels) in <main>': undefined local variable or method `abc' for main:Object (NameError)
        from t.rb:3:in `loop'
        from t.rb:3:in `block in <main>'
like image 121
falsetru Avatar answered Nov 15 '22 08:11

falsetru


For syntax error catching, rescue must use explict Exception class (without this, rescue catch only StandardError) :

Thread.new {  
begin
  abc.puts ef
rescue  Exception => e
  puts "error #{e}"
end
}

see Why can't `rescue` catch exception classes other than `StandardError` by default?

like image 21
raubarede Avatar answered Nov 15 '22 09:11

raubarede