#runtime trace error

202 messages ยท Page 1 of 1 (latest)

grim cradle
#

Hello, i am trying to use the package runtime/trace

package main

import (
    "fmt"
    "os"
    "os/signal"
    "runtime/trace"
    "syscall"
)

func main() {
    f, err := os.Create("trace.out")
    if err != nil {
        panic(err)
    }
    defer f.Close()

    err = trace.Start(f)
    if err != nil {
        panic(err)
    }
    defer trace.Stop()

    // random stuff
    a := 0
    for i := 0; i < 10; i++ {
        a += i
    }
    fmt.Println(a)
    // end random stuff

    sigint := make(chan os.Signal, 1)
    signal.Notify(sigint, syscall.SIGINT)

    <-sigint // this creates the problem

    fmt.Println("THE END")
}

When running the above program i get the following error when using cmd/trace tool. Does anyone know why ? If i remove the line "<-sigint" (ie i don't wait for the Ctrl+C signal), it works.

> go tool trace trace.out
failed to parse trace: no consistent ordering of events possible

As anyone encountered this error ? How can i fix it without removing the signal catching thing (i need it to exit my app)

river willow
#

https://pkg.go.dev/cmd/trace have you read this yet? It looks like you are creating trace.out as an empty file but the docs suggest that it is expecting a specific format (and lists 3 ways to generate it)

neat parrot
#

The trace writer is buffered so you need to stop first.
Are you trying to use the file while the program is running?

river willow
#

I don't know if I"m just misreading what you ahve and you're doing it correctly though ๐Ÿ™ƒ

grim cradle
#

thank you for your response @river willow @neat parrot !

grim cradle
neat parrot
#

The code is correct.

#

But are you trying to use the output before the program has finished?

grim cradle
#

no

neat parrot
#

So you read it after the program has exited?

grim cradle
#

test it yourself, the sigint mess everything up

#

if you comment it, it works fine

neat parrot
#

So you're pressing Ctrl+C before you check the output?

grim cradle
#

yes

#

if you add a print after "<-sigint", you can see that the end of the code is indeed executed (and therefore, both defer too)

#

i really don't understand why the tracing does not work in that example

neat parrot
#

It works for me.

grim cradle
#

really ? did you use the exact same code ?

neat parrot
#

I run it, press Ctrl+C and then run go tool trace trace.out

#

Yes

grim cradle
#

wtf

#

are you using windows ?

neat parrot
#

No

river willow
#

actually I don't get an error

neat parrot
#

Click on the link

river willow
neat parrot
#

Yes, in the console

river willow
neat parrot
#

Yup, that's the stuff

grim cradle
neat parrot
grim cradle
#

i am doing the same thing

river willow
#

I'm on a mac

#

in case that makes a difference here..?

neat parrot
#

I'm on Fedora Linux. What are you on @grim cradle ?

grim cradle
#

windows 10

#

go version go1.19.3 windows/amd64

#

oh

#

i tested on another computer (windows 11) i got the same problem

#

using go1.19.4

neat parrot
#

hmmm gophereyes

river willow
#

I keep trying to find that error message in the source code but come up dry. Wonder if its an OS thing?

neat parrot
#

Are you using WSL?

grim cradle
#

the emulator thing of windows ?

neat parrot
#

Aye

grim cradle
#

i don't have it installed i think

neat parrot
#

Okay

#

So you're just on plain Windows?

grim cradle
#

yup

neat parrot
#

No WSL, no MinGW?

grim cradle
#

nope

neat parrot
#

Okay, hmmm

grim cradle
#

maybe i am doing something wrong but i rly dont know what

river willow
river willow
# grim cradle nope

might be worthwhile to grab WSL real quick, see if it happens on like an ubuntu install?

neat parrot
#

What if you're adding this?

defer signal.Stop(sigint)

Put it under the call to signal.Notify

river willow
#

also when I was on windows I just genuinely really liked WSL, specifically WSL2. It even had a vscode integration from the windows side

grim cradle
#

if it does not work either i am the problem lol

#

i tested outside of vscode it does not help either :/

river willow
river willow
neat parrot
#

Maybe try to use os.Interruptinstead of using syscall

grim cradle
grim cradle
river willow
grim cradle
#
    sigint := make(chan os.Signal, 1)
    signal.Notify(sigint, os.Interrupt)
    defer signal.Stop(sigint)
river willow
#

I don't think its your code, at least, because both Kangaroo and myself can run it

grim cradle
#

well it can be a problem of my code on windows

#

like your screen is suggesting

neat parrot
#

It's a Windows problem

#

Maybe also hook onto sysvall.SIGTERM?

river willow
grim cradle
neat parrot
#

Windows is the odd one here.

grim cradle
#

(my code is stuck forever)

neat parrot
#

Windows handles these kinds of things very differently

grim cradle
#
    sigint := make(chan os.Signal, 1)
    signal.Notify(sigint, syscall.SIGINT)
    defer signal.Stop(sigint)

    sigterm := make(chan os.Signal, 1)
    signal.Notify(sigterm, syscall.SIGTERM)
    defer signal.Stop(sigterm)

    <-sigint
    <-sigterm
neat parrot
#

oooh, no

#

You use one handler for both

grim cradle
#

oh

neat parrot
#

You can also use context instead of channel but:

    ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
    defer cancel()

I tend to put that at the top of my programs and then pass that context on.

#

And then to wait, just do <-ctx.Done()

#

The Notifyand NotifyContext accepts one or more signals. So you can just add as many of them as you want.

grim cradle
#
    ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT)
    defer cancel()

    <-ctx.Done()
neat parrot
#

It doesn't stop?

#

Or you're not getting a proper trace output?

grim cradle
#

not a proper trace output

grim cradle
neat parrot
#

Yes

grim cradle
#

Note: you must actually build the program for this to work. If you run the program via go run in a console and send a SIGTERM via ^C, the signal is written into the channel and the program responds, but appears to drop out of the loop unexpectedly. This is because the SIGRERM goes to go run as well! (This has cause me substantial confusion!)

#

do you understand this response ? it has a lot of upvote on stackoverflow

neat parrot
#

Aye

#

build before you run

grim cradle
#

i did build however but it doesnt help

neat parrot
#

So instead of run, use buildand then run the resulting executable

grim cradle
#

i did it but its not working

neat parrot
#

hmmm

grim cradle
#

well

#

fuck windows

#

i miss apt

neat parrot
#

It's not POSIX compliant.

#

dnf ๐Ÿ™

#

The signal thing is a POSIX thing. Windows doesn't support it.

grim cradle
#

that sucks

#

it's a really important feature

neat parrot
#

Yes

grim cradle
#

i can stop my program using an rpc call or idk but it is complicated for nothing

neat parrot
#

aha

river willow
#

WSL2 is pretty magic though

neat parrot
#

What if you end it through the task manager?

grim cradle
#

well i need to "catch" that i want to exit the program in order to save its state basically

#

signaling was the way to go ๐Ÿฅฒ

neat parrot
#

Have you tried ending it with task manager?

grim cradle
#

how ?

#

i can just terminate de process

neat parrot
#

You can find it in the task manager and end it there

#

And what happens when you do that?

grim cradle
#

the trace is empty

neat parrot
#

But no errors?

grim cradle
#

i will try with other signals

#

"THE END" is not printed

neat parrot
#

oh ๐Ÿ˜

river willow
#

exit on a timer?

grim cradle
#

what ?

#

you mean sleep after " <-sig" ?

river willow
#

do you need to exit from catching a signal here? or for testing purposes could you replace it with like a ticker?

grim cradle
#

if i remove the signal catching the tracing works fine

#
package main

import (
    "fmt"
    "os"
    "runtime/trace"
    "time"
)

func main() {
    f, err := os.Create("trace.out")
    if err != nil {
        panic(err)
    }
    defer f.Close()

    err = trace.Start(f)
    if err != nil {
        panic(err)
    }
    defer trace.Stop()

    // random stuff
    a := 0
    for i := 0; i < 10; i++ {
        a += i
    }
    fmt.Println(a)
    // end random stuff

    time.Sleep(1 * time.Second)
    fmt.Println("THE END")
}

this works

river willow
#

ok, so now you're just wrestling windows signals. do you need to do that to advance your original goal? just checking if you are yak shaving

grim cradle
#

well that is my goal since the beginning

#

the tracing is working without the signal catching BUT i need to catch the exit of my app AND be able to trace it

river willow
#

gotcha! damn, was hoping you could sidestep this lol

#

well, go give WSL2 a try cause fuck windows. the install process is pretty painless too

grim cradle
#

I will do that i think

#

My code will run on a linux server in the end anyway

grim cradle
#

@river willow @neat parrot f windows

#

wsl is the best thing ever with vscode integration

#

so easy to use

river willow
#

hahaha yes it is so good

#

grats! glad it you got past it

grim cradle
#

yep ! thank you for your help !

#

i will let you know if i have a response on my github issues if you're interested

neat parrot
#

The Regionand Task feature in the tracing looks nice. ๐Ÿ™‚

grim cradle
#

where do you find those ?

neat parrot
#

In the trace package

grim cradle
#

i see

neat parrot
#

So you can get tracing for specific parts of your program.

grim cradle
#

i dont use context nowhere in my program :/

neat parrot
#

It's really helpful.

#

I always use it for the signal handling.

grim cradle
#

i know it is usefull for cancelling and timeout

#

i now some people create a context in the main and pass it arount everywhere in their code

neat parrot
#

So if you need context without timeout but don't want something to block until the end of times, give it the context that you create in main()

#

The important thing to remember is that you shouldn't use that for everything. Sometimes you would rather have a context with timeout that's completely separate from the one that's cancelled by signals.

grim cradle
#

i thought the idea was to have like a tree of context. where if one context failed (timeout or canceled), its children die as well

neat parrot
#

Yes

grim cradle
#

so it seems logical to always derive from an earlier context

neat parrot
#

But, keep in mind that the context that's cancelled by a signal can be cancelled whenever.

grim cradle
#

sure

neat parrot
#

For example, if you have an HTTP server, you want to start the shutdown once the context is cancelled.

#

But you want to create a new context with a timeout for the shutdown of the HTTP server.

#

Also, if you're doing database operations, it's better to give that operation a certain amount of time before it gets cancelled instead of just having it get cancelled by the signal.

grim cradle
#

oh i see

grim cradle
neat parrot
#

So if a signal comes in at the same time as the database operation is taking place, it's better to let it run and then return

#

Yes, context.Background() is what you use when you don't want to inherit from another context.

grim cradle
neat parrot
#

You should give time for something to finish

#

Then you'd get clean exists

#

Otherwise you'll abort any operation when a signal comes in

grim cradle
#

mmmmh ok

neat parrot
#

Give things time to complete.

grim cradle
#

you just let it finish even if the rq is "useless"

neat parrot
#

I wouldn't say it's useless.

grim cradle
#

in the sense that it is not used like it was intended before the canceling

neat parrot
#

If you've started an operation, you would want to complete it or let it fail for other reasons than a signal asking the program to exit

#

What rq?

grim cradle
#

request

neat parrot
#

HTTP request by a client?

#

Like, your program making a request?

grim cradle
#

idk, i mean a general thing that takes time and that can be timed out

neat parrot
#

It depends if a signal should stop things instantly or if you want everything that has started to finish.

#

Because everything isn't possible to cancel.

#

Sometimes you have 3 things that need to be done and you only want all 3 or none of them to run.

#

So it's better to let it finish all 3 steps

grim cradle
#

oooh ok

neat parrot
#

Instead of half way through the last step

grim cradle
#

like two sql request for example

neat parrot
#

You have to think about this along the way as you use context. Should you let it run until it completes or times out using context or should it abort as soon as the signal arrives?

#

Aye

grim cradle
#

i dont have experience in backend dev but i am sure it is very powerful

#

when dealing with lots of client db etc