odin-lang / Odin

Odin Programming Language
https://odin-lang.org
BSD 3-Clause "New" or "Revised" License
6.53k stars 569 forks source link

Test runner sometimes hangs #3880

Closed adimemir-prog closed 2 months ago

adimemir-prog commented 2 months ago

Context

'destroy' here refers to the procedure group destroy from core:math/big package

Code

package main

import "core:c/libc"
import "core:os"
//----------------------------------
import "core:fmt"
import "core:math"
import "core:math/big"
import "core:mem"
import "core:slice"
import "core:testing"
import "vendor:raylib"

TWO : big.Int

main :: proc()
{
    fmt.println("Entering main.")

    build_mode();

    fmt.println("Exiting main.")
} // main

init2 :: proc() {
    big.atoi(&TWO,"2");
}

deinit2 :: proc() {
    big.destroy(&TWO)
}

@test
test_mode :: proc(t: ^testing.T) {

    track: mem.Tracking_Allocator
    mem.tracking_allocator_init(&track, context.allocator)
    defer mem.tracking_allocator_destroy(&track)
    context.allocator = mem.tracking_allocator(&track)

    fmt.println("\nWe will be informed of a memory leak and a bad free, but program execution continues\n");
    ptr : ^i32 = new(i32); ptr2 := new(i32)
    free(ptr); 
    free(ptr);

    fmt.println("Again it just warns due to a double delete, but execution continues")
    arr := [dynamic]i32{1}; delete(arr); delete(arr)

    fmt.println("\nHere however, we are informed of a bad free and in addition to that the program execution gets stuck")
    init2();
    deinit2();
    deinit2();
    fmt.println("Unable to exit normally while testing due to the three lines above; program gets stuck\n")
    fmt.println("When main.exe is opened in Windows CMD terminal, even Ctrl-C is not enough we need to close the window")

    for _, leak in track.allocation_map {
        fmt.printf("%v leaked %m\n", leak.location, leak.size)
    }
    for bad_free in track.bad_free_array {
        fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
    }

}

build_mode :: proc() {

    track: mem.Tracking_Allocator
    mem.tracking_allocator_init(&track, context.allocator)
    defer mem.tracking_allocator_destroy(&track)
    context.allocator = mem.tracking_allocator(&track)

    fmt.println("\nWe will be informed of a memory leak and a bad free, but program execution continues\n");
    ptr : ^i32 = new(i32); ptr2 := new(i32)
    free(ptr); 
    free(ptr);

    fmt.println("Again it just warns due to a double delete, but execution continues")
    arr := [dynamic]i32{1}; delete(arr); delete(arr)

    fmt.println("\nOkay, we are in build mode so, these three lines will not cause the execution to get stuck")
    init2();
    deinit2();
    deinit2();

    for _, leak in track.allocation_map {
        fmt.printf("%v leaked %m\n", leak.location, leak.size)
    }
    for bad_free in track.bad_free_array {
        fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
    }

    fmt.println("Able to exit normally when building an executable normally")
}

Expected Behavior

There should not be a difference.

Current Behavior

There is a difference described below.

Steps to Reproduce

build normally : odin build main.odin -file then build in test mode : odin test main.odin -file

Build mode log:

Entering main.

We will be informed of a memory leak and a bad free, but program execution continues

Again it just warns due to a double delete, but execution continues

Okay, we are in build mode so, these three lines will not cause the execution to get stuck E:/code/_odin/workspaces/bug/jul6_2024_LINK_ERROR/test/code.odin(73:33) leaked 4b E:/code/_odin/workspaces/bug/jul6_2024_LINK_ERROR/test/code.odin(75:2) allocation 1BA2F05EFB8 was freed badly E:/code/_odin/workspaces/bug/jul6_2024_LINK_ERROR/test/code.odin(78:39) allocation 1BA2F05F618 was freed badly E:/code/odin-windows-amd64-dev-2024-06/core/math/big/internal.odin(1853:4) allocation 1BA2F06A048 was freed badly Able to exit normally when building an executable normally Exiting main.

Test mode log:

[Package: main] [Test: test4]

We will be informed of a memory leak and a bad free, but program execution continues

Again it just warns due to a double delete, but execution continues

Here however, we are informed of a bad free and in addition to that the program execution gets stuck Unable to exit normally while testing due to the three lines above; program gets stuck

When main.exe is opened in Windows CMD terminal, even Ctrl-C is not enough we need to close the window E:/code/_odin/workspaces/bug/jul6_2024_LINK_ERROR/test/code.odin(50:33) leaked 4b E:/code/_odin/workspaces/bug/jul6_2024_LINK_ERROR/test/code.odin(52:2) allocation 1F823450878 was freed badly E:/code/_odin/workspaces/bug/jul6_2024_LINK_ERROR/test/code.odin(55:39) allocation 1F823451238 was freed badly E:/code/odin-windows-amd64-dev-2024-06/core/math/big/internal.odin(1853:4) allocation 1F823451458 was freed badly

Kelimion commented 2 months ago

We will be informed of a memory leak and a bad free, but program execution continues Again it just warns due to a double delete, but execution continues

The way you phrase this, it makes it sound like it's surprising that execution continues. It's printing a report of all leaks and double frees it found at the end of the program's execution, so of course it's not going to stop after the first failure.

If you want it to panic after the first failure, you can replace it with fmt.panicf, but that'll just mean spending a longer time fixing all your leaks in the end.

Here however, we are informed of a bad free and in addition to that the program execution gets stuck Unable to exit normally while testing due to the three lines above; program gets stuck

I don't know why you think it's important to highlight the bad free. It also happened in the other example, but "here however" suggests this bad free didn't occur previously. It's a red herring.

It's great that you have an example that illustrates the difference between building and testing, but you're really burying the lede in your description of the problem.

But long story short is that I can't replicate your bug: image

Kelimion commented 2 months ago

I also cleaned up your example to compile with -vet -strict-style to get rid of unused imports and the like. Because they're unused they should have no impact on the bug's occurrence, but it did make it easier to follow what's going on.

package bug

//----------------------------------
import "core:fmt"
import "core:math/big"
import "core:mem"
import "core:testing"

TWO: big.Int

main :: proc() {
    fmt.println("Entering main.")
    build_mode()
    fmt.println("Exiting main.")
}

init2 :: proc() {
    big.atoi(&TWO, "2")
}

deinit2 :: proc() {
    big.destroy(&TWO)
}

@test
test_mode :: proc(t: ^testing.T) {
    track: mem.Tracking_Allocator
    mem.tracking_allocator_init(&track, context.allocator)
    defer mem.tracking_allocator_destroy(&track)
    context.allocator = mem.tracking_allocator(&track)

    fmt.println("\nWe will be informed of a memory leak and a bad free, but program execution continues\n")
    ptr : ^i32 = new(i32)
    free(ptr)
    free(ptr)

    fmt.println("Again it just warns due to a double delete, but execution continues")
    arr := [dynamic]i32{1}; delete(arr); delete(arr)

    fmt.println("\nHere however, we are informed of a bad free and in addition to that the program execution gets stuck")
    init2()
    deinit2()
    deinit2()
    fmt.println("Unable to exit normally while testing due to the three lines above; program gets stuck\n")
    fmt.println("When main.exe is opened in Windows CMD terminal, even Ctrl-C is not enough we need to close the window")

    for _, leak in track.allocation_map {
        fmt.printf("%v leaked %m\n", leak.location, leak.size)
    }
    for bad_free in track.bad_free_array {
        fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
    }
}

build_mode :: proc() {
    track: mem.Tracking_Allocator
    mem.tracking_allocator_init(&track, context.allocator)
    defer mem.tracking_allocator_destroy(&track)
    context.allocator = mem.tracking_allocator(&track)

    fmt.println("\nWe will be informed of a memory leak and a bad free, but program execution continues\n")
    ptr : ^i32 = new(i32)
    free(ptr)
    free(ptr)

    fmt.println("Again it just warns due to a double delete, but execution continues")
    arr := [dynamic]i32{1}; delete(arr); delete(arr)

    fmt.println("\nOkay, we are in build mode so, these three lines will not cause the execution to get stuck")
    init2()
    deinit2()
    deinit2()

    for _, leak in track.allocation_map {
        fmt.printf("%v leaked %m\n", leak.location, leak.size)
    }
    for bad_free in track.bad_free_array {
        fmt.printf("%v allocation %p was freed badly\n", bad_free.location, bad_free.memory)
    }

    fmt.println("Able to exit normally when building an executable normally")
}
Kelimion commented 2 months ago

Odin: dev-2024-06-nightly:f745a1c47

You may want to update to the latest commit. I can't make the bug occur on it.

adimemir-prog commented 2 months ago

Odin: dev-2024-06-nightly:f745a1c47

You may want to update to the latest commit. I can't make the bug occur on it.

I think i posted a slightly different file than a intended to, i will edit the issue

adimemir-prog commented 2 months ago

Odin: dev-2024-06-nightly:f745a1c47

You may want to update to the latest commit. I can't make the bug occur on it.

I tried to replicate it again and it is very weird but i could not replicate it with powershell, but i have encountered this execution getting stuck again with CMD.

if you open Windows cmd directly, then cd to the bug.odin root directory and type odin test bug.odin -file or odin test .

you will encounter

first time: execution hangs as i have described

second time: LINK : fatal error LNK1104: cannot open file 'E:\code_odin\workspaces\bug\jul6_2024_LINK_ERROR\bug.exe'

Kelimion commented 2 months ago

Updated the title to reflect the actually suggested problem.

Kelimion commented 2 months ago

I think i posted a slightly different file than a intended to, i will edit the issue

Did you update the code listing? On the current commit of Odin, I can't replicate this on Windows 10 Professional with cmd.exe with the code you provided.

I've run the test 20x in a row. Not a single hang or even so much as a whisper of a delay before exiting.

adimemir-prog commented 2 months ago

No that was a misunderstanding on my part; the code as it is now is fine, i am running on odin compiler version dev-2024-06-nightly:f745a1c47, i will switch to the latest release and try again.

Kelimion commented 2 months ago

I'll close the issue for now. If you still run into the issue on the latest Odin, let us know and we can reopen it if need be.

adimemir-prog commented 2 months ago

I'll close the issue for now. If you still run into the issue on the latest Odin, let us know and we can reopen it if need be.

I have tried again with compiler odin-windows-amd64-nightly+2024-07-05.

And it still is the case that the execution gets stuck when "odin test ." is run within Windows CMD console but not when run within powershell.