[#34647] fork 不可能な環境での test_argv0_noarg — wanabe <s.wanabe@...>

ワナベと申します。

13 messages 2008/05/11
[#34667] Re: fork 不可能な環境での test_argv0_noarg — Yukihiro Matsumoto <matz@...> 2008/05/13

まつもと ゆきひろです

[#34742] Ruby 1.8.7-preview3 has been released — "Akinori MUSHA" <knu@...>

 Ruby 1.8.7-preview3 をリリースしました。

14 messages 2008/05/18
[#34744] Re: [ruby-list:44957] Ruby 1.8.7-preview3 has been released — Takahiro Kambe <taca@...> 2008/05/19

お疲れ様です。

[#34800] Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...>

木村です。

18 messages 2008/05/22
[#34801] Re: Windows2000上でtrunkがビルドできない — "U.Nakamura" <usa@...> 2008/05/22

こんにちは、なかむら(う)です。

[#34824] Re: Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...> 2008/05/23

木村です。

[#34850] Re: Windows2000上でtrunkがビルドできない — KIMURA Koichi <kimura.koichi@...> 2008/05/26

木村です。

[#34854] Re: Windows2000上でtrunkがビルドできない — "U.Nakamura" <usa@...> 2008/05/26

こんにちは、なかむら(う)です。

[#34889] Ruby 1.8.7-preview4 test-all failed in OpenSSL::TestSSL — Nobuhiro IMAI <nov@...>

いまいです。

10 messages 2008/05/29

[ruby-dev:34707] Re: fork 不可能な環境での test_argv0_noarg

From: Tanaka Akira <akr@...>
Date: 2008-05-14 16:08:11 UTC
List: ruby-dev #34707
In article <87ve1hmde3.fsf@fsij.org>,
  Tanaka Akira <akr@fsij.org> writes:

> 実行すると NotImplementedError になり、respond_to? で調べる
> と偽になる特殊なメソッドを導入するのはどうですかね。
>
> undef みたいなかんじで。

実装するとこんな感じでしょうか。

個々のメソッドについてはとりあえず fork と File.lchmod だけ
対処してあります。

GNU/Linux には lchmod がないので、File.respond_to?(:lchmod)
は false になり、File.lchmod を呼び出すと
NotImplementedError になります。

% ./ruby -ve '
p File.respond_to?(:lchmod)
File.lchmod("foo", 0777)'
ruby 1.9.0 (2008-05-14 revision 16419) [i686-linux]
false
-e:3:in `lchmod': lchmod() function is unimplemented on this machine (NotImplementedError)
        from -e:3:in `<main>'

Index: include/ruby/intern.h
===================================================================
--- include/ruby/intern.h	(revision 16419)
+++ include/ruby/intern.h	(working copy)
@@ -252,6 +252,7 @@ int rb_method_boundp(VALUE, ID, int);
 VALUE rb_eval_cmd(VALUE, VALUE, int);
 int rb_obj_respond_to(VALUE, ID, int);
 int rb_respond_to(VALUE, ID);
+void rb_define_notimplement_method_id(VALUE mod, ID id, int noex);
 void rb_interrupt(void);
 VALUE rb_apply(VALUE, ID, VALUE);
 void rb_backtrace(void);
Index: include/ruby/node.h
===================================================================
--- include/ruby/node.h	(revision 16419)
+++ include/ruby/node.h	(working copy)
@@ -498,6 +498,8 @@ NODE *rb_node_newnode(enum node_type,VAL
 NODE* rb_method_node(VALUE klass, ID id);
 int rb_node_arity(NODE* node);
 
+int rb_notimplement_body_p(NODE*);
+
 struct global_entry *rb_global_entry(ID);
 VALUE rb_gvar_get(struct global_entry *);
 VALUE rb_gvar_set(struct global_entry *, VALUE);
Index: proc.c
===================================================================
--- proc.c	(revision 16419)
+++ proc.c	(working copy)
@@ -935,6 +935,15 @@ method_owner(VALUE obj)
     return data->oclass;
 }
 
+static VALUE
+method_notimplemented_p(VALUE obj)
+{
+    struct METHOD *data;
+
+    Data_Get_Struct(obj, struct METHOD, data);
+    return rb_notimplement_body_p(data->body) ? Qtrue : Qfalse;
+}
+
 /*
  *  call-seq:
  *     obj.method(sym)    => method
@@ -1763,6 +1772,7 @@ Init_Proc(void)
     rb_define_method(rb_cMethod, "name", method_name, 0);
     rb_define_method(rb_cMethod, "owner", method_owner, 0);
     rb_define_method(rb_cMethod, "unbind", method_unbind, 0);
+    rb_define_method(rb_cMethod, "notimplemented?", method_notimplemented_p, 0);
     rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
     rb_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1);
 
@@ -1780,6 +1790,7 @@ Init_Proc(void)
     rb_define_method(rb_cUnboundMethod, "name", method_name, 0);
     rb_define_method(rb_cUnboundMethod, "owner", method_owner, 0);
     rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
+    rb_define_method(rb_cUnboundMethod, "notimplemented?", method_notimplemented_p, 0);
 
     /* Module#*_method */
     rb_define_method(rb_cModule, "instance_method", rb_mod_instance_method, 1);
Index: class.c
===================================================================
--- class.c	(revision 16419)
+++ class.c	(working copy)
@@ -759,25 +759,40 @@ rb_obj_singleton_methods(int argc, VALUE
 void
 rb_define_method_id(VALUE klass, ID name, VALUE (*func)(ANYARGS), int argc)
 {
-    rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC);
+    if (func)
+        rb_add_method(klass, name, NEW_CFUNC(func,argc), NOEX_PUBLIC);
+    else
+        rb_define_notimplement_method_id(klass, name, NOEX_PUBLIC);
 }
 
 void
 rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
 {
-    rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC);
+    ID id = rb_intern(name);
+    if (func)
+        rb_add_method(klass, id, NEW_CFUNC(func, argc), NOEX_PUBLIC);
+    else
+        rb_define_notimplement_method_id(klass, id, NOEX_PUBLIC);
 }
 
 void
 rb_define_protected_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
 {
-    rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PROTECTED);
+    ID id = rb_intern(name);
+    if (func)
+        rb_add_method(klass, id, NEW_CFUNC(func, argc), NOEX_PROTECTED);
+    else
+        rb_define_notimplement_method_id(klass, id, NOEX_PROTECTED);
 }
 
 void
 rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc)
 {
-    rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE);
+    ID id = rb_intern(name);
+    if (func)
+        rb_add_method(klass, id, NEW_CFUNC(func, argc), NOEX_PRIVATE);
+    else
+        rb_define_notimplement_method_id(klass, id, NOEX_PRIVATE);
 }
 
 void
Index: process.c
===================================================================
--- process.c	(revision 16419)
+++ process.c	(working copy)
@@ -2394,10 +2394,10 @@ rb_fork(int *status, int (*chfunc)(void*
  *  fork doesn't copy other threads.
  */
 
+#if defined(HAVE_FORK) && !defined(__NetBSD__)
 static VALUE
 rb_f_fork(VALUE obj)
 {
-#if defined(HAVE_FORK) && !defined(__NetBSD__)
     rb_pid_t pid;
 
     rb_secure(2);
@@ -2423,11 +2423,10 @@ rb_f_fork(VALUE obj)
       default:
 	return PIDT2NUM(pid);
     }
+}
 #else
-    rb_notimplement();
+#define rb_f_fork 0
 #endif
-}
-
 
 /*
  *  call-seq:
Index: eval_method.c
===================================================================
--- eval_method.c	(revision 16419)
+++ eval_method.c	(working copy)
@@ -18,6 +18,8 @@ struct cache_entry {		/* method hash tab
 static struct cache_entry cache[CACHE_SIZE];
 static int ruby_running = 0;
 
+static NODE *notimplement_body = 0;
+
 void
 rb_clear_cache(void)
 {
@@ -403,6 +405,12 @@ rb_export_method(VALUE klass, ID name, I
 }
 
 int
+rb_notimplement_body_p(NODE *method)
+{
+    return method == notimplement_body ? Qtrue : Qfalse;
+}
+
+int
 rb_method_boundp(VALUE klass, ID id, int ex)
 {
     NODE *method;
@@ -411,6 +419,8 @@ rb_method_boundp(VALUE klass, ID id, int
 	if (ex && (method->nd_noex & NOEX_PRIVATE)) {
 	    return Qfalse;
 	}
+        if (rb_notimplement_body_p(method->nd_body))
+	    return Qfalse;
 	return Qtrue;
     }
     return Qfalse;
@@ -645,10 +655,49 @@ rb_mod_alias_method(VALUE mod, VALUE new
     return mod;
 }
 
+static VALUE
+notimplement_cfunc(VALUE obj)
+{
+    rb_notimplement();
+}
+
+void
+rb_define_notimplement_method_id(VALUE mod, ID id, int noex)
+{
+    rb_add_method(mod, id, notimplement_body, noex);
+}
+
+static VALUE
+rb_mod_notimplemented_method(int argc, VALUE *argv, VALUE mod)
+{
+    int i;
+    if (ruby_cbase() == rb_cObject && mod == rb_cObject) {
+        rb_secure(4);
+    }
+
+    for (i = 0; i < argc; i++) {
+        ID id = rb_to_id(argv[i]);
+
+        if (rb_safe_level() >= 4 && !OBJ_TAINTED(mod)) {
+            rb_raise(rb_eSecurityError, "Insecure: can't undef `%s'",
+                     rb_id2name(id));
+        }
+        rb_frozen_class_p(mod);
+        if (id == object_id || id == __send__ || id == init) {
+            rb_warn("notimplementing `%s' may cause serious problem", rb_id2name(id));
+        }
+	rb_define_notimplement_method_id(mod, id, NOEX_PUBLIC);
+    }
+    return mod;
+}
+
 static void
 Init_eval_method(void)
 {
     rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, -1);
     rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, -1);
     rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
+    rb_global_variable(&notimplement_body);
+    notimplement_body = NEW_CFUNC(notimplement_cfunc, -1);
+    rb_define_private_method(rb_cModule, "notimplemented_method", rb_mod_notimplemented_method, -1);
 }
Index: file.c
===================================================================
--- file.c	(revision 16419)
+++ file.c	(working copy)
@@ -1901,12 +1901,7 @@ rb_file_s_lchmod(int argc, VALUE *argv)
     return LONG2FIX(n);
 }
 #else
-static VALUE
-rb_file_s_lchmod(int argc, VALUE *argv)
-{
-    rb_notimplement();
-    return Qnil;		/* not reached */
-}
+#define rb_file_s_lchmod 0
 #endif
 
 struct chown_args {
Index: test/ruby/test_notimp.rb
===================================================================
--- test/ruby/test_notimp.rb	(revision 0)
+++ test/ruby/test_notimp.rb	(revision 0)
@@ -0,0 +1,33 @@
+require 'test/unit'
+
+class TestNotImplement < Test::Unit::TestCase
+  class C
+    notimplemented_method :n
+    def x() end
+  end
+
+  def test_respond_to
+    assert_equal(false, C.new.respond_to?(:n))
+    assert_equal(true, C.new.respond_to?(:x))
+  end
+
+  def test_call
+    assert_raise(NotImplementedError) { C.new.n }
+    assert_nothing_raised { C.new.x }
+  end
+
+  def test_method
+    m = C.new.method(:n)
+    assert(m.notimplemented?)
+    m = C.new.method(:x)
+    assert(!m.notimplemented?)
+  end
+
+  def test_umethod
+    m = C.instance_method(:n)
+    assert(m.notimplemented?)
+    m = C.instance_method(:x)
+    assert(!m.notimplemented?)
+  end
+
+end
-- 
[田中 哲][たなか あきら][Tanaka Akira]

In This Thread