Bug #9207

Build failure on Windows 8.1 with VS2013 x64

Added by Heesob Park over 1 year ago. Updated over 1 year ago.

[ruby-core:58835]
Status:Closed
Priority:Normal
Assignee:Nobuyoshi Nakada
ruby -v:ruby 2.1.0dev (2013-12-02 trunk 43958) [x64-mswin64_120] Backport:1.9.3: UNKNOWN, 2.0.0: UNKNOWN

Description

On Windows 8.1, I cannot build trunk with the VS2013 64-bit C compiler.

C:\work\ruby-2.1.0-r43958>win32\configure.bat
Creating Makefile.new
"type `nmake' to make ruby."

C:\work\ruby-2.1.0-r43958>nmake

Microsoft (R) Program Maintenance Utility Version 12.00.21005.1
Copyright (C) Microsoft Corporation. All rights reserved.

    CC = cl -nologo
    LD = cl -nologo
    LDSHARED = cl -nologo -LD
    CFLAGS = -MD -Zi -W2 -wd4996 -we4028 -we4142 -O2sy-  -Zm600
    XCFLAGS = -DRUBY_EXPORT -I. -I.ext/include/x64-mswin64_120 -I./include -

I. -I./missing
CPPFLAGS =
DLDFLAGS = -incremental:no -debug -opt:ref -opt:icf -dll
SOLIBS =
Creating config.h
.ext\include\x64-mswin64_120\ruby\config.h updated
Creating config.status
compiling main.c
main.c
compiling dmydln.c
dmydln.c
compiling miniruby.rc
compiling miniinit.c
miniinit.c
compiling miniprelude.c
miniprelude.c
copying dummy probes.h
compiling array.c
array.c
compiling bignum.c
bignum.c
compiling class.c
class.c
compiling compar.c
compar.c
compiling complex.c
complex.c
compiling dir.c
dir.c
compiling dln_find.c
dln_find.c
compiling encoding.c
encoding.c
compiling enum.c
enum.c
compiling enumerator.c
enumerator.c
compiling error.c
error.c
compiling eval.c
eval.c
compiling load.c
load.c
compiling proc.c
proc.c
compiling file.c
file.c
compiling gc.c
gc.c
compiling hash.c
hash.c
compiling inits.c
inits.c
compiling io.c
io.c
compiling marshal.c
marshal.c
compiling math.c
math.c
compiling node.c
node.c
compiling numeric.c
numeric.c
compiling object.c
object.c
compiling pack.c
pack.c
compiling parse.c
parse.c
compiling process.c
process.c
compiling random.c
random.c
compiling range.c
range.c
compiling rational.c
rational.c
compiling re.c
re.c
compiling regcomp.c
regcomp.c
compiling regenc.c
regenc.c
compiling regerror.c
regerror.c
compiling regexec.c
regexec.c
compiling regparse.c
regparse.c
compiling regsyntax.c
regsyntax.c
compiling ruby.c
ruby.c
compiling safe.c
safe.c
compiling signal.c
signal.c
compiling sprintf.c
sprintf.c
compiling st.c
st.c
compiling strftime.c
strftime.c
compiling string.c
string.c
compiling struct.c
struct.c
compiling time.c
time.c
compiling transcode.c
transcode.c
compiling util.c
util.c
compiling variable.c
variable.c
compiling version.c
version.c
compiling compile.c
compile.c
compiling debug.c
debug.c
compiling iseq.c
iseq.c
compiling vm.c
vm.c
compiling vm_dump.c
vm_dump.c
compiling vm_backtrace.c
vm_backtrace.c
compiling vm_trace.c
vm_trace.c
compiling thread.c
thread.c
compiling cont.c
cont.c
compiling ./enc/ascii.c
ascii.c
compiling ./enc/us_ascii.c
us_ascii.c
compiling ./enc/unicode.c
unicode.c
compiling ./enc/utf_8.c
utf_8.c
compiling newline.c
newline.c
compiling ./missing/crypt.c
crypt.c
compiling ./missing/ffs.c
ffs.c
compiling ./missing/langinfo.c
langinfo.c
compiling ./missing/lgamma_r.c
lgamma_r.c
compiling ./missing/strlcat.c
strlcat.c
compiling ./missing/strlcpy.c
strlcpy.c
compiling win32/win32.c
win32.c
compiling win32/file.c
file.c
compiling ./missing/setproctitle.c
setproctitle.c
compiling dmyext.c
dmyext.c
oldnames.lib user32.lib advapi32.lib shell32.lib ws2_32.lib iphlpapi.lib imagehl
p.lib shlwapi.lib
linking miniruby.exe
ruby 2.1.0dev (2013-12-02 trunk 43958) [x64-mswin64_120]
rbconfig.rb updated
generating enc.mk
./enc/make_encmake.rb: stack level too deep (SystemStackError)
NMAKE : fatal error U1077: '.\miniruby.exe' : return code '0x1'
Stop.

fix_stackerror.patch Magnifier (846 Bytes) Heesob Park, 12/05/2013 11:23 PM

History

#1 Updated by Heesob Park over 1 year ago

I found that r43859 introduced this issue.

Before r43859, the build works fine on Windows 8.1

#2 Updated by Hiroshi SHIBATA over 1 year ago

  • Assignee set to Usaku NAKAMURA

usa
Do you have dev environment of Windows 8.1...?

#3 Updated by Heesob Park over 1 year ago

I found what is going on with Windows 8.1.
In Windows 8.x, an allocated address can take over 32-bit value unlike Windows 7.
And 64-bit value is not a SPECIAL_CONST value on Windows.

Thus, when ruby calls rb_hash function with 64bit address value, the following call chains.

rb_hash
-> rb_exec_recursive_outer
-> recursive_check
-> rb_hash_lookup2
-> st_lookup
-> rb_any_hash

-> rb_hash # infinite recursion occurred!

I made a draft patch.

#4 Updated by Nobuyoshi Nakada over 1 year ago

=begin
Does identhash help?

diff --git a/thread.c b/thread.c
index f111a5f..c5b2e4c 100644
--- a/thread.c
+++ b/thread.c
@@ -4738,6 +4738,16 @@ rb_thread_shield_destroy(VALUE self)
/* variables for recursive traversals */
static ID recursive_key;

+extern const struct st_hash_type st_hashtype_num;
+
+static VALUE
+ident_hash_new(void)
+{
+ VALUE hash = rb_hash_new();
+ rb_hash_tbl_raw(hash)->type = &st_hashtype_num;
+ return hash;
+}
+
/*
* Returns the current "recursive list" used to detect recursion.
* This list is a hash table, unique for the current thread and for
@@ -4751,7 +4761,7 @@ recursive_list_access(void)
VALUE sym = ID2SYM(rb_frame_this_func());
VALUE list;
if (NIL_P(hash) || !RB_TYPE_P(hash, T_HASH)) {
- hash = rb_hash_new();
+ hash = ident_hash_new();
rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
list = Qnil;
}
@@ -4759,7 +4769,7 @@ recursive_list_access(void)
list = rb_hash_aref(hash, sym);
}
if (NIL_P(list) || !RB_TYPE_P(list, T_HASH)) {
- list = rb_hash_new();
+ list = ident_hash_new();
rb_hash_aset(hash, sym, list);
}
return list;
@@ -4820,7 +4830,7 @@ recursive_push(VALUE list, VALUE obj, VALUE paired_obj)
else {
if (!RB_TYPE_P(pair_list, T_HASH)){
VALUE other_paired_obj = pair_list;
- pair_list = rb_hash_new();
+ pair_list = ident_hash_new();
rb_hash_aset(pair_list, other_paired_obj, Qtrue);
rb_hash_aset(list, obj, pair_list);
}
=end

#5 Updated by Nobuyoshi Nakada over 1 year ago

=begin
Sorry, it was incomplete.

diff --git i/lib/pp.rb w/lib/pp.rb
index 0091ddf..e43b3fd 100644
--- i/lib/pp.rb
+++ w/lib/pp.rb
@@ -132,17 +132,17 @@ class PP < PrettyPrint
# and preserves the previous set of objects being printed.
def guard_inspect_key
if Thread.current[:recursive_key] == nil
- Thread.current[:recursive_key] = {}.taint
+ Thread.current[:recursive_key] = {}.compare_by_identity.taint
end

    if Thread.current[:__recursive_key__][:inspect] == nil
  • Thread.current[:recursive_key][:inspect] = {}.taint
  •    Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity.taint
    end
    
    save = Thread.current[:__recursive_key__][:inspect]
    
    begin
    
  •    Thread.current[:__recursive_key__][:inspect] = {}.taint
    
  •    Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity.taint
      yield
    ensure
      Thread.current[:__recursive_key__][:inspect] = save
    

    @@ -175,18 +175,16 @@ class PP < PrettyPrint
    # Object#pretty_print_cycle is used when +obj+ is already
    # printed, a.k.a the object reference chain has a cycle.
    def pp(obj)

  •  id = obj.object_id
    

  •  if check_inspect_key(id)
    
  •  if check_inspect_key(obj)
      group {obj.pretty_print_cycle self}
      return
    end
    
    begin
    
  •    push_inspect_key(id)
    
  •    push_inspect_key(obj)
      group {obj.pretty_print self}
    ensure
    
  •    pop_inspect_key(id) unless PP.sharing_detection
    
  •    pop_inspect_key(obj) unless PP.sharing_detection
    end
    

    end

diff --git i/thread.c w/thread.c
index f111a5f..f2ee3cc 100644
--- i/thread.c
+++ w/thread.c
@@ -4738,6 +4738,16 @@ rb_thread_shield_destroy(VALUE self)
/* variables for recursive traversals */
static ID recursive_key;

+extern const struct st_hash_type st_hashtype_num;
+
+static VALUE
+ident_hash_new(void)
+{
+ VALUE hash = rb_hash_new();
+ rb_hash_tbl_raw(hash)->type = &st_hashtype_num;
+ return hash;
+}
+
/*
* Returns the current "recursive list" used to detect recursion.
* This list is a hash table, unique for the current thread and for
@@ -4751,7 +4761,7 @@ recursive_list_access(void)
VALUE sym = ID2SYM(rb_frame_this_func());
VALUE list;
if (NIL_P(hash) || !RB_TYPE_P(hash, T_HASH)) {
- hash = rb_hash_new();
+ hash = ident_hash_new();
rb_thread_local_aset(rb_thread_current(), recursive_key, hash);
list = Qnil;
}
@@ -4759,7 +4769,7 @@ recursive_list_access(void)
list = rb_hash_aref(hash, sym);
}
if (NIL_P(list) || !RB_TYPE_P(list, T_HASH)) {
- list = rb_hash_new();
+ list = ident_hash_new();
rb_hash_aset(hash, sym, list);
}
return list;
@@ -4774,12 +4784,7 @@ recursive_list_access(void)
static VALUE
recursive_check(VALUE list, VALUE obj_id, VALUE paired_obj_id)
{
-#if SIZEOF_LONG == SIZEOF_VOIDP
#define OBJ_ID_EQL(obj_id, other) ((obj_id) == (other))
-#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
- #define OBJ_ID_EQL(obj_id, other) (RB_TYPE_P((obj_id), T_BIGNUM) ? \
- rb_big_eql((obj_id), (other)) : ((obj_id) == (other)))
-#endif

  VALUE pair_list = rb_hash_lookup2(list, obj_id, Qundef);
  if (pair_list == Qundef)

@@ -4820,7 +4825,7 @@ recursive_push(VALUE list, VALUE obj, VALUE paired_obj)
else {
if (!RB_TYPE_P(pair_list, T_HASH)){
VALUE other_paired_obj = pair_list;
- pair_list = rb_hash_new();
+ pair_list = ident_hash_new();
rb_hash_aset(pair_list, other_paired_obj, Qtrue);
rb_hash_aset(list, obj, pair_list);
}
@@ -4861,7 +4866,6 @@ struct exec_recursive_params {
VALUE (*func) (VALUE, VALUE, int);
VALUE list;
VALUE obj;
- VALUE objid;
VALUE pairid;
VALUE arg;
};
@@ -4873,13 +4877,13 @@ exec_recursive_i(RB_BLOCK_CALL_FUNC_ARGLIST(tag, data))
VALUE result = Qundef;
int state;

  • recursive_push(p->list, p->objid, p->pairid);
  • recursive_push(p->list, p->obj, p->pairid); PUSH_TAG(); if ((state = EXEC_TAG()) == 0) { result = (*p->func)(p->obj, p->arg, FALSE); } POP_TAG();
  • recursive_pop(p->list, p->objid, p->pairid);
  • recursive_pop(p->list, p->obj, p->pairid); if (state) JUMP_TAG(state); return result; @@ -4903,13 +4907,12 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE struct exec_recursive_params p; int outermost; p.list = recursive_list_access();
  • p.objid = rb_obj_id(obj);
    p.obj = obj;
    p.pairid = pairid;
    p.arg = arg;
    outermost = outer && !recursive_check(p.list, ID2SYM(recursive_key), 0);

  • if (recursive_check(p.list, p.objid, pairid)) {

  • if (recursive_check(p.list, p.obj, pairid)) {
    if (outer && !outermost) {
    rb_throw_obj(p.list, p.list);
    }
    @@ -4953,7 +4956,7 @@ rb_exec_recursive(VALUE (func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
    VALUE
    rb_exec_recursive_paired(VALUE (
    func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
    {

  • return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 0);

  • return exec_recursive(func, obj, paired_obj, arg, 0);
    }

/*
@@ -4977,7 +4980,7 @@ rb_exec_recursive_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
VALUE
rb_exec_recursive_paired_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
{
- return exec_recursive(func, obj, rb_obj_id(paired_obj), arg, 1);
+ return exec_recursive(func, obj, paired_obj, arg, 1);
}

/*
=end

#6 Updated by Heesob Park over 1 year ago

Your patch fixed this issue.

#7 Updated by Hiroshi SHIBATA over 1 year ago

  • Assignee changed from Usaku NAKAMURA to Nobuyoshi Nakada

#8 Updated by Heesob Park over 1 year ago

This issue was solved with changeset r44034.

#9 Updated by Hiroshi SHIBATA over 1 year ago

  • Status changed from Open to Closed

Also available in: Atom PDF