[#47790] [ruby-trunk - Bug #7097][Open] Thread locals don't work inside Enumerator — "tenderlovemaking (Aaron Patterson)" <aaron@...>

32 messages 2012/10/01
[#47791] [ruby-trunk - Bug #7097][Assigned] Thread locals don't work inside Enumerator — "kosaki (Motohiro KOSAKI)" <kosaki.motohiro@...> 2012/10/01

[#47792] Re: [ruby-trunk - Bug #7097][Assigned] Thread locals don't work inside Enumerator — Aaron Patterson <tenderlove@...> 2012/10/01

On Tue, Oct 02, 2012 at 03:05:17AM +0900, kosaki (Motohiro KOSAKI) wrote:

[#47798] Re: [ruby-trunk - Bug #7097][Assigned] Thread locals don't work inside Enumerator — SASADA Koichi <ko1@...> 2012/10/01

(2012/10/02 3:12), Aaron Patterson wrote:

[#47800] Re: [ruby-trunk - Bug #7097][Assigned] Thread locals don't work inside Enumerator — SASADA Koichi <ko1@...> 2012/10/01

(2012/10/02 8:22), SASADA Koichi wrote:

[#47832] [ruby-trunk - Feature #7106][Open] FileUtils.touch should allow touching the symlink itself rather than the file the link points to — "cirrusthinking (Alessandro Diaferia)" <alessandro@...>

18 messages 2012/10/04

[#47847] [ruby-trunk - Bug #7110][Open] CGI: Add support for HTML5 <header> tag — "stomar (Marcus Stollsteimer)" <redmine@...>

16 messages 2012/10/05

[#47870] [ruby-trunk - Bug #7123][Open] Segmentation fault in ruby 1.9.3-p194 — "mscottford (M. Scott Ford)" <scott@...>

13 messages 2012/10/09

[#47880] [ruby-trunk - Bug #7134][Open] Signal handling bug in Mac OS X — "auastro (Andy Kitchen)" <kitchen.andy+rubybug@...>

17 messages 2012/10/10

[#47881] [ruby-trunk - Bug #7135][Open] GC bug in Ruby 1.9.3-p194? — "alexdowad (Alex Dowad)" <alexinbeijing@...>

21 messages 2012/10/10

[#47887] [ruby-trunk - Bug #7137][Open] Date.parse overly lenient when attempting to parse Monday? — "garysweaver (Gary Weaver)" <garysweaver@...>

12 messages 2012/10/10

[#47930] [ruby-trunk - Feature #7148][Open] Improved Tempfile w/o DelegateClass — "Glass_saga (Masaki Matsushita)" <glass.saga@...>

14 messages 2012/10/12

[#47970] [ruby-trunk - Bug #7158][Open] require is slow in its bookkeeping; can make Rails startup 2.2x faster — "gregprice (Greg Price)" <price@...>

30 messages 2012/10/14

[#48027] [Backport93 - Backport #7172][Open] [[Ruby 1.9:]] fix rbconfig for --enable-load-relative (v2) — "mpapis (Michal Papis)" <mpapis@...>

13 messages 2012/10/16

[#48053] [ruby-trunk - Bug #7180][Open] set_trace_func with error in proc block locks up Ruby with 100% cpu usage and no way to exit without killing proc — "garysweaver (Gary Weaver)" <garysweaver@...>

8 messages 2012/10/17

[#48072] [ruby-trunk - Bug #7184][Open] --disable-gems commandline parameter does not show up with ruby -h — "steenslag (siep korteling)" <s.korteling@...>

10 messages 2012/10/18

[#48130] [ruby-trunk - Bug #7200][Open] Setting external encoding with BOM| — "brixen (Brian Ford)" <brixen@...>

14 messages 2012/10/21

[#48191] [ANN] 2.0.0 feature freeze — Yusuke Endoh <mame@...>

Japanese later; 日本語は後で

37 messages 2012/10/24
[#48696] Re: [ANN] 2.0.0 feature freeze — SASADA Koichi <ko1@...> 2012/11/01

(2012/10/24 5:39), Yusuke Endoh wrote:

[#48260] [ruby-trunk - Bug #7214][Open] Ruby 2.0 breaks support for some debugging tools — "banister (john mair)" <jrmair@...>

22 messages 2012/10/25

[#48315] [ruby-trunk - Bug #7220][Open] StringIO#initialize_copy causes aliasing between the objects — "brixen (Brian Ford)" <brixen@...>

13 messages 2012/10/26

[#48413] [ruby-trunk - Bug #7221][Open] Unable to compile kgio under 1.9.3 with error: ruby-1.9.3-<plvl>/lib/ruby/1.9.1/mkmf.rb:597:in `Integer': can't convert nil into Integer (TypeError) — "davidderyldowney (David Deryl Downey)" <me@...>

9 messages 2012/10/27

[#48549] [ruby-trunk - Feature #7240][Open] Inheritable #included/#extended Hooks For Modules — "apotonick (Nick Sutterer)" <apotonick@...>

14 messages 2012/10/29

[#48551] [ruby-trunk - Feature #7241][Open] Enumerable#to_h proposal — "nathan.f77 (Nathan Broadbent)" <nathan.f77@...>

23 messages 2012/10/29

[#48552] [ruby-trunk - Bug #7242][Open] Bignum mathematical accuracy regression in r31695 — "mhall (Matthew Hall)" <mhall@...>

11 messages 2012/10/29

[ruby-core:48387] [ruby-trunk - Feature #6714] Code injection framework

From: "ko1 (Koichi Sasada)" <redmine@...>
Date: 2012-10-26 22:21:33 UTC
List: ruby-core #48387
Issue #6714 has been updated by ko1 (Koichi Sasada).

Target version changed from 2.0.0 to next minor

Sorry, maybe I don't have enough time to make it until 2.0 release.

I will introduce C level (helper?) API to implement this feature if I can.
----------------------------------------
Feature #6714: Code injection framework
https://bugs.ruby-lang.org/issues/6714#change-31700

Author: ko1 (Koichi Sasada)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: next minor


=begin
= Abstract

Introducing code injection framework.  Different from set_trace_func(), this framework injects codes only specified points.

Note that this proposal is not implemented and well designed (only rough idea) but I dumped it to discuss about this topic.  It has (huge) possibility to miss 2.0 spec deadline (should be 3.0 spec?).


= Background

To trace, debug, profile and any analysis ruby code, Ruby provides `set_trace_func()' method.  set_trace_func() is enough powerful to do them.  However set_trace_func() injects codes every tracing points.  It cause huge performance impact if you have interest restricted places.

Another problem is that set_trace_func() can not affect program behavior.  For example, we can not insert type checking code for specific method invocation.

Related works with introducing codes are described below.  Please point out if you know another related works.

== Bytecode instrumentation

JVM has JVMTI interface <http://docs.oracle.com/javase/6/docs/platform/jvmti/jvmti.html#bci> to inject any code with bytecode instrumentation.  It can be done because JVM bytecode is well defined and become concrete specification.  However, Ruby doesn't have any well-defined common bytecode and difficult to make such common bytecode (at least Ruby 2.0 spec deadline, this August).

Manipulate bytecode directly has other problems:
* Needs more knowledge about bytecode
* Difficult to make `well-formed' bytecode sequence

== AOP (Aspect Oriented Programming)

Aspect-Oriented programming frameworks provides `join points' which we can insert codes <http://www.eclipse.org/aspectj/doc/released/progguide/language.html>.  Such `join points' design is well abstracted comparing with bytecode instrumentation.

In fact, AOT compilers such as Aspect-J use bytecode instrumentation.

== Module#prepend

We already have Module#prepend that enable to insert any program before/after method invocation.

Example:

  module EachTracer # call tracing method before/after each method
    def each(*args)
      before_each
      begin
        super # call original each
      ensure
        after_each
      end
    end
  end
  
  class Array
    prepend EachTracer
  
    def before_each
      p:before_each
    end
    def after_each
      p:after_each
    end
  end
  
  %w(a b c).each{|c|}
  #=> outputs :before_each and :after_each

However, Module#prepend only works for method invocation.

= Proposal

Introduce code injection framework.  It should provide two features: (1) "where should insert codes?" and (2) "what code should be insert?".

RubyVM::InstructionSequence#each_point(point_name) is temporal API for (1).  each_point invoke block with CodePoint object.  CodePint#set_proc (or something) is for (2).

Example (it is rough API idea):

  def m1
    m2(1)
    m2(1, 2, 3)
    m3()
    m4()
  end
  
  # insert proc before m2 method invocation
  method(:m1).iseq.each_point(:before_call){|point|
    # point is CodePoint object.
    if point.selector == :m2
      point.set_proc{|*args|
        p "before call m2 with #{args.inspect}"
      }
    end
  }
  
  # another idea
  method(:m1).iseq.each_point(:invoke_method){|point|
    if point.selector == :m2
      point.insert_proc_before{|*args|
        p "before call m2 with #{args.inspect}"
      }
    else point.selector == :m3
      point.insert_proc_after{|retval|
        p "after call m2 with return value #{retval}"
      }
    else point.slector == :m4
      point.replace_proc{|*args|
        p "cancel invoking m4 and call this proc instead"
      }
    end
  end

Injection points are categorized into 3 types:

* (1) before/after invoke something
  * method call (before method call)
  * method call (after method call)
  * block invocation (before)
  * block invocation (after)
  * super invocation (before)
  * super invocation (after)

* (2) enter/leave (not needed?)
  * method (enter) (set_trace_func/call)
  * method (leave) (set_trace_func/return)
  * class/module definition (enter) (set_trace_func/class)
  * class/module definition (leave) (set_trace_func/end)
  * block (enter)
  * block (leave)
  * rescue (enter)
  * rescue (leave)
  * ensure (enter)
  * ensure (leave)

* (3) misc
  * read variable ($gv, @iv, @@cv)
  * write variable ($gv, @iv, @@cv)
  * read constant (Const)
  * define constant (Const)
  * method definition
  * newline (set_trace_func/line)

This proposal can introduce (limited) code manipulation without any bytecode knowledge.

== Usecase

* inserting specific break points for debugger
* inserting specific analysis points for profiler
* inserting type checking code generated by rdoc
* making Aspect-J like tool (note that Module#prepend is enough if you only want to replace method invocation behavior)

Any other idea?

== Limitation

It is impossible to inject any code into methods implemented by C.

I'm afraid that this proposed API makes magical (unreadable) codes for script kiddies :P

I repeat it again: Note that this proposal is not implemented and well designed (only rough idea) but I dumped it to discuss about this topic.  It has (huge) possibility to miss 2.0 spec deadline (should be 3.0 spec?).

Thanks,
Koichi

=end



-- 
http://bugs.ruby-lang.org/

In This Thread