HaxeFoundation / hxcpp

Runtime files for c++ backend for haxe
Other
294 stars 187 forks source link

4.0.64 produces segmentation fault in Linux #865

Open andyli opened 4 years ago

andyli commented 4 years ago

The api.haxe.org doc generation failed with seg fault with hxcpp 4.0.64. https://travis-ci.org/HaxeFoundation/api.haxe.org/builds/608451154#L846

I've just pinned hxcpp version to 4.0.52 and CI worked as expected now.

sonygod commented 4 years ago

got the same error on ubuntu

image

@hughsando

sonygod commented 4 years ago
import haxe.io.Bytes;
import haxe.MainLoop;

//using tink.CoreApi;

class CustomTrace {
    public static function init() {
        var oldTrace = haxe.Log.trace;
        haxe.Log.trace = function(v:Dynamic, ?pos:haxe.PosInfos) {
            oldTrace("[" + Date.now().toString() + "] " + Std.string(v), pos);
        };
    }
}

class KLSFGEN {
    public static function main() {
        CustomTrace.init();

        GenKLSFJSONBytes.genMulThread();
    }
}

class GenKLSF {
    public static function computeAllChoices(data:Ref<Array<Int>>, n:Int, outLen:Int, startIndex:Int, m:Int, arr:Array<Int>, arrIndex:Int,
            result:Ref<Array<Array<Int>>>) {
        if (m == 0) {
            result.value.push(arr.copy());

            return;
        }

        var endIndex = n - m;
        // for(int i=startIndex; i<=endIndex; i++)

        var i = startIndex;

        while (i <= endIndex) {
            arr[arrIndex] = data.value[i];
            computeAllChoices(data, n, outLen, i + 1, m - 1, arr, arrIndex + 1, result);

            i++;
        }
    }
}

class GenKLSFJSONBytes {
    public static function genMulThread() {
        // CustomTrace.init();

        var data:Ref<Array<Int>> = [for (i in 1...21) i];

        var result:tink.core.Ref<Array<Array<Int>>> = [];

        GenKLSF.computeAllChoices(data, data.value.length, 8, 0, 8, [], 0, result);
        var len = result.value.length;

        var index = 0;

        var threadCounts = 15;

        var eachCount = Std.int(len / threadCounts);

        trace(eachCount);
        var totals = 0;

        for (i in 0...threadCounts) {
            var start = i * eachCount;
            var end = (i + 1) * eachCount;

            var total = 0;
            // trace('start=$start end=$end');
            for (k in start...end) {
                if (total > end) {
                    trace('i=$i start=$start end=$end total=$total k=$k');
                    throw "fuck!";
                }
                // trace(total);
                total += 1;
            }

            totals += total;

            trace('totals=$totals  total=$total i=$i');
        }

        trace(totals);
        //  return;
        for (i in 0...threadCounts) {
            MainLoop.addThread(function() {
                var r:Ref<Bytes> = Bytes.alloc(322560);

                var itemBytes = Bytes.alloc(8);
                var from = i * eachCount;
                var to = (i + 1) * eachCount;
                for (k in from...to) {
                    var currentIndex = k + i;

                    var item = result.value[currentIndex];

                    for (i in 0...item.length) {
                        itemBytes.set(i, item[i]);
                    }
                    new PermutationBit(itemBytes, function(d) {
                        index++;
                        // var remain = len - index;
                        // r.value.fill(0,r.value.length,0);
                    }, r);

                    if (index % 1000 == 0) {
                        trace(index);
                    }

                    if (index == totals) {
                        trace("finish!");
                    }
                }
            });
        }
    }
}

class PermutationBit {
    private var result = [];

    static var total:Int = 1;

    private var callBack:Array<Array<Int>>->Void;

    var lastIndex:UInt = 0;
    var len = 0;

    public function new(array:Bytes, callBack:Bytes->Void, result:Ref<Bytes>) {
        // trace(total);

        len = array.length;

        if (total == 1) {
            var arr = [for (ii in 0...len) ii + 1];
            var i = arr.length - 1;

            while (i > 0) {
                var v = arr[i];
                total *= v;
                i--;
            }
            total *= len;
        }

        heapPermutation(array, len, total, callBack, result);
        //  heapPermutation(array,len,total,callBack);
    }

    function copyBytes(b:Bytes) {
        // var a = Bytes.alloc(b.length);
        // a.blit(0, b, 0, b.length);

        return b;
    }

    private function heapPermutation(a:Bytes, size:UInt, total:Int, callBack:Bytes->Void, result:Ref<Bytes>) {
        if (size == 1) {
            // trace(a);
            var b = copyBytes(a);
            result.value.blit(lastIndex, b, 0, b.length); // (copyBytes(b));
            lastIndex += len;
            if (lastIndex == total) {
                callBack(result);
            }
        }

        for (i in 0...size) {
            var s = size - 1;

            heapPermutation(a, s, total, callBack, result);

            // if (size % 2 == 1) {
            if (size & 1 == 1) {
                var temp = a.get(0); // a[0];
                // a[0] = a[size - 1];

                a.set(0, a.get(size - 1));
                //  a[size - 1] = temp;
                a.set(size - 1, temp);
            } else {
                var temp = a.get(i); // a[i];
                // a[i] = a[size - 1];
                //  a[size - 1] = temp;

                a.set(i, a.get(size - 1));

                a.set(size - 1, temp);
            }
        }
    }
}
hughsando commented 4 years ago

This line seems a little odd: var currentIndex = k + i; since currentIndex becomes >= total. Should it maybe be just k?

sonygod commented 4 years ago

oh,yes ,thanks .

this test seem hxcpp is 6x times faster than hl target. wowoo!!

hxcpp only take less than 30s hl :will cost more than 3 minutes

hughsando commented 4 years ago

@andyli I could not reproduce this - but maybe because I am running haxe 4.02 and it appears this test is running with 3.4.7. Is it possible to run this with 4.0.2 to see if this is where the issue is?

sonygod commented 4 years ago

is possible create Bytes more than 1G in hxcpp if my pc more than 32G memory ?

Bytes.alloc(1024 1024 1024 * 32) //32g

@hughsando

andyli commented 4 years ago

@hughsando Indeed I cannot reproduce it locally with Haxe 4.0.2. It happened with Haxe 3.4.7 in Debian Buster running in WSL2.

I can try bisect hxcpp, but I'm not sure which commit 4.0.64 is at since there is no tag...

andyli commented 4 years ago

I did a git bisect with Haxe 3.4.7 in Debian Buster running in WSL2. 2558f93359b3f75ece7db12fd1259c6cd500b82b is the first bad commit.

Simn commented 4 years ago

Oh come on... :(

hughsando commented 4 years ago

I can reproduce it on a linux vm. It looks like one of the ascii strings gets a character code=240 at the end, and this breaks the logic. This might come from the regex, or the regex may just be a symptom given that it works when you use haxe 4.0. It might be something that has been fixed in 4.0 in the standard library - eg StringTools - and not back-ported into 3.4.x. I will try moving some haxe files around and see if this fixes things.