Bug #9207

Build failure on Windows 8.1 with VS2013 x64

Added by Heesob Park 5 months ago. Updated 4 months ago.

[ruby-core:58835]
Status:Closed
Priority:Normal
Assignee:Nobuyoshi Nakada
Category:-
Target version:-
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-mswin64120\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
dlnfind.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
vmdump.c
compiling vm
backtrace.c
vmbacktrace.c
compiling vm
trace.c
vmtrace.c
compiling thread.c
thread.c
compiling cont.c
cont.c
compiling ./enc/ascii.c
ascii.c
compiling ./enc/us
ascii.c
usascii.c
compiling ./enc/unicode.c
unicode.c
compiling ./enc/utf
8.c
utf8.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
lgammar.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-mswin64120]
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 5 months ago

I found that r43859 introduced this issue.

Before r43859, the build works fine on Windows 8.1

#2 Updated by Hiroshi SHIBATA 5 months ago

  • Assignee set to Usaku NAKAMURA

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

#3 Updated by Heesob Park 4 months 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.

rbhash
-> rb
execrecursiveouter
-> recursivecheck
-> rb
hashlookup2
-> st
lookup
-> rbanyhash

-> rb_hash # infinite recursion occurred!

I made a draft patch.

#4 Updated by Nobuyoshi Nakada 4 months 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 @@ rbthreadshielddestroy(VALUE self)
/* variables for recursive traversals */
static ID recursive
key;

+extern const struct sthashtype sthashtypenum;
+
+static VALUE
+identhashnew(void)
+{
+ VALUE hash = rbhashnew();
+ rbhashtblraw(hash)->type = &sthashtypenum;
+ 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
listaccess(void)
VALUE sym = ID2SYM(rb
framethisfunc());
VALUE list;
if (NILP(hash) || !RBTYPEP(hash, THASH)) {
- hash = rbhashnew();
+ hash = identhashnew();
rbthreadlocalaset(rbthreadcurrent(), recursivekey, hash);
list = Qnil;
}
@@ -4759,7 +4769,7 @@ recursivelistaccess(void)
list = rbhasharef(hash, sym);
}
if (NILP(list) || !RBTYPEP(list, THASH)) {
- list = rbhashnew();
+ list = identhashnew();
rbhashaset(hash, sym, list);
}
return list;
@@ -4820,7 +4830,7 @@ recursivepush(VALUE list, VALUE obj, VALUE pairedobj)
else {
if (!RBTYPEP(pairlist, THASH)){
VALUE otherpairedobj = pairlist;
- pair
list = rbhashnew();
+ pairlist = identhashnew();
rb
hashaset(pairlist, otherpairedobj, Qtrue);
rbhashaset(list, obj, pair_list);
}
=end

#5 Updated by Nobuyoshi Nakada 4 months 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 guardinspectkey
if Thread.current[:recursive_key] == nil
- Thread.current[:recursive_key] = {}.taint
+ Thread.current[:recursive_key] = {}.comparebyidentity.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#prettyprintcycle 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 @@ rbthreadshielddestroy(VALUE self)
    /* variables for recursive traversals */
    static ID recursive
    key;

    +extern const struct sthashtype sthashtypenum;
    +
    +static VALUE
    +identhashnew(void)
    +{

  • VALUE hash = rbhashnew();

  • rbhashtblraw(hash)->type = &sthashtype_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 @@ recursivelistaccess(void) VALUE sym = ID2SYM(rbframethisfunc()); VALUE list; if (NILP(hash) || !RBTYPEP(hash, T_HASH)) {
  • hash = rbhashnew();

  • hash = identhashnew();
    rbthreadlocalaset(rbthreadcurrent(), recursivekey, hash);
    list = Qnil;
    }
    @@ -4759,7 +4769,7 @@ recursivelistaccess(void)
    list = rbhasharef(hash, sym);
    }
    if (NILP(list) || !RBTYPEP(list, THASH)) {

  • list = rbhashnew();

  • list = identhashnew();
    rbhashaset(hash, sym, list);
    }
    return list;
    @@ -4774,12 +4784,7 @@ recursivelistaccess(void)
    static VALUE
    recursivecheck(VALUE list, VALUE objid, VALUE pairedobjid)
    {
    -#if SIZEOFLONG == SIZEOFVOIDP
    #define OBJIDEQL(objid, other) ((objid) == (other))
    -#elif SIZEOFLONGLONG == SIZEOF_VOIDP

  • #define OBJIDEQL(objid, other) (RBTYPEP((objid), T_BIGNUM) ? \

  • rbbigeql((objid), (other)) : ((objid) == (other)))
    -#endif

    VALUE pairlist = rbhashlookup2(list, objid, Qundef);
    if (pairlist == Qundef)
    @@ -4820,7 +4825,7 @@ recursive
    push(VALUE list, VALUE obj, VALUE pairedobj)
    else {
    if (!RB
    TYPEP(pairlist, THASH)){
    VALUE other
    pairedobj = pairlist;

  •  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 execrecursiveparams {
    VALUE (*func) (VALUE, VALUE, int);
    VALUE list;
    VALUE obj;

  • VALUE objid;
    VALUE pairid;
    VALUE arg;
    };
    @@ -4873,13 +4877,13 @@ execrecursivei(RBBLOCKCALLFUNCARGLIST(tag, data))
    VALUE result = Qundef;
    int state;

  • recursive_push(p->list, p->objid, p->pairid);

  • recursivepush(p->list, p->obj, p->pairid);
    PUSH
    TAG();
    if ((state = EXECTAG()) == 0) {
    result = (*p->func)(p->obj, p->arg, FALSE);
    }
    POP
    TAG();

  • recursive_pop(p->list, p->objid, p->pairid);

  • recursivepop(p->list, p->obj, p->pairid);
    if (state)
    JUMP
    TAG(state);
    return result;
    @@ -4903,13 +4907,12 @@ execrecursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE
    struct exec
    recursiveparams p;
    int outermost;
    p.list = recursive
    list_access();

  • p.objid = rbobjid(obj);
    p.obj = obj;
    p.pairid = pairid;
    p.arg = arg;
    outermost = outer && !recursivecheck(p.list, ID2SYM(recursivekey), 0);

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

  • if (recursivecheck(p.list, p.obj, pairid)) {
    if (outer && !outermost) {
    rb
    throwobj(p.list, p.list);
    }
    @@ -4953,7 +4956,7 @@ rb
    execrecursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
    VALUE
    rb
    execrecursivepaired(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE paired_obj, VALUE arg)
    {

  • return execrecursive(func, obj, rbobjid(pairedobj), arg, 0);

  • return execrecursive(func, obj, pairedobj, arg, 0);
    }

    /*
    @@ -4977,7 +4980,7 @@ rbexecrecursiveouter(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
    VALUE
    rb
    execrecursivepairedouter(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairedobj, VALUE arg)
    {

  • return execrecursive(func, obj, rbobjid(pairedobj), arg, 1);

  • return execrecursive(func, obj, pairedobj, arg, 1);
    }

    /*
    =end

#6 Updated by Heesob Park 4 months ago

Your patch fixed this issue.

#7 Updated by Hiroshi SHIBATA 4 months ago

  • Assignee changed from Usaku NAKAMURA to Nobuyoshi Nakada

#8 Updated by Heesob Park 4 months ago

This issue was solved with changeset r44034.

#9 Updated by Hiroshi SHIBATA 4 months ago

  • Status changed from Open to Closed

Also available in: Atom PDF