Project

General

Profile

Actions

Bug #9207

closed

Build failure on Windows 8.1 with VS2013 x64

Added by phasis68 (Heesob Park) over 10 years ago. Updated over 10 years ago.

Status:
Closed
Target version:
-
ruby -v:
ruby 2.1.0dev (2013-12-02 trunk 43958) [x64-mswin64_120]
[ruby-core:58835]

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.


Files

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

Updated by phasis68 (Heesob Park) over 10 years ago

I found that r43859 introduced this issue.

Before r43859, the build works fine on Windows 8.1

Updated by hsbt (Hiroshi SHIBATA) over 10 years ago

  • Assignee set to usa (Usaku NAKAMURA)

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

Updated by phasis68 (Heesob Park) over 10 years 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.

Updated by nobu (Nobuyoshi Nakada) over 10 years 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

Updated by nobu (Nobuyoshi Nakada) over 10 years 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

Updated by phasis68 (Heesob Park) over 10 years ago

Your patch fixed this issue.

Updated by hsbt (Hiroshi SHIBATA) over 10 years ago

  • Assignee changed from usa (Usaku NAKAMURA) to nobu (Nobuyoshi Nakada)

Updated by phasis68 (Heesob Park) over 10 years ago

This issue was solved with changeset r44034.

Updated by hsbt (Hiroshi SHIBATA) over 10 years ago

  • Status changed from Open to Closed
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0