Project

General

Profile

Actions

Feature #10211

closed

Implement Signal.current_trap(sig)

Added by kyrylo (Kyrylo Silin) about 10 years ago. Updated about 9 years ago.

Status:
Feedback
Assignee:
-
Target version:
-
[ruby-core:64830]

Description

Here's pseudocode by ko1:

def trap2(sig)
  previous_proc = Signal.current_trap(sig)
  Signal.trap(sig){
    previous_proc.call if previous_proc
    yield
  }
end
 
trap2(:INT){...}

Motivation

I'm developing a gem that allows using multiple callbacks for a trap: [[https://github.com/kyrylo/multitrap]]
It's pretty simple (and slightly broken). The problem is that if you earlier had defined traps and then
required my library, it would discard your previously defined callbacks.
The library overrides Signal.trap and stores callbacks in a hash. However, it stores only new callbacks.
I cannot access previously defined callbacks for signals. They are stored in GET_VM()->trap_list, which
isn't exposed neither to Ruby nor to the C extension API. I know when you define a trap, it returns a proc.
However, nobody typicaly stores it, so there's no way to access it. So if my gem loads after this assignment,
I'm unable to capture that proc, hence I always overwrite previous "traps". This library might be useful if you
want to define a trap that conflicts with some other gem you depend on, which defines its own trap for the
same signal.

So I need some way to access the callbacks.

Updated by ko1 (Koichi Sasada) about 10 years ago

  • Description updated (diff)

Updated by akr (Akira Tanaka) about 10 years ago

Any problem with the return value of trap?

% ruby -e '
def trap2(sig)
  previous_proc = Signal.trap(sig){
    previous_proc.call if previous_proc
    yield
  }
end

trap(:INT) { p 1 }
trap2(:INT) { p 2 }
Process.kill :INT, $$
'
1
2

Updated by akr (Akira Tanaka) about 10 years ago

  • Status changed from Open to Feedback

Updated by kyrylo (Kyrylo Silin) about 10 years ago

Akira Tanaka wrote:

Any problem with the return value of trap?

There's no problem with it by itself. However, there are some libraries like RSpec that use trap
and not store its return value: https://github.com/rspec/rspec-core/blob/d06ffe85b4513dba296abc653090191806963da0/lib/rspec/core/runner.rb#L150

There's no way to access that proc (unless you monkey-patch the method
it is defined in, but it's crazy :).

Updated by kyrylo (Kyrylo Silin) about 10 years ago

Well, even monkey-patching won't help.

Updated by nobu (Nobuyoshi Nakada) about 10 years ago

I can't get your point.
Do you want to get the previous trap defined before RSpec is loaded?

Updated by deivid (David Rodríguez) about 10 years ago

I happen to need something like this too.

I'd like to be able to override RSpec's trap somehow. For example, if someone types something in byebug or pry's prompt, we surely don't want to quit rspec but only empty the input written so far by the user and print another prompt.

Updated by kyrylo (Kyrylo Silin) about 10 years ago

Nobuyoshi Nakada wrote:

I can't get your point.
Do you want to get the previous trap defined before RSpec is loaded?

I want to get the trap defined by RSpec (and probably other gems loaded
before Multitrap that define various trap callbacks for other signals).

If I define a new trap('INT') within my RSpec tests, it overwrites the
RSpec one.

Updated by deivid (David Rodríguez) about 10 years ago

Disregard my previous message, I thought all traps were executed from last to first, but only last one is. I guess that's why you're implementing Multitrap, right Kyrylo?

Updated by kyrylo (Kyrylo Silin) about 10 years ago

David Rodríguez wrote:

Disregard my previous message, I thought all traps were executed from last to first, but only last one is. I guess that's why you're implementing Multitrap, right Kyrylo?

Exactly :)

Updated by kyrylo (Kyrylo Silin) about 9 years ago

I think we can close this. Thanks everyone for help! I finally figured out how to do that without modifying Ruby.

I updated https://github.com/kyrylo/multitrap

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0