Eliminate printing path to the source code when a program panics

434 views
Skip to first unread message

Nikita Yenin

unread,
Jun 5, 2016, 2:35:43 AM6/5/16
to golan...@googlegroups.com

Hi, Is it possible to eliminate printing of the complete path to the source code when a program panics? Any options that can be used during go build or go install?

For e.g... Can "/Users/nyenin/dev/src/errorf.go:10" be simply "errorf.go:10"

Sample run of a program that hit a panic.

goroutine 1 [running]:

panic(0xb8300, 0xc82006c1e0)

/usr/local/go/src/runtime/panic.go:481 +0x3e6

main.printer(0x0, 0x0, 0x0, 0x0)

/Users/nyenin/dev/src/errorf.go:19 +0x91

main.main()

/Users/nyenin/dev/src/errorf.go:10 +0x127

exit status 2


Steve Phillips

unread,
Jun 5, 2016, 7:04:58 AM6/5/16
to golang-nuts, nikit...@protonmail.com
Hmm, I also don't see how deterministic builds can work if paths for your own machine are part of the binary being run, and I thought builds were deterministic as of https://github.com/golang/go/commit/5bbb98df0960f57dca73cb7640456608d4cc0917

...or are you not using go1.7beta1, Nikita?  Thanks.

Ian Lance Taylor

unread,
Jun 5, 2016, 1:49:54 PM6/5/16
to Nikita Yenin, golan...@googlegroups.com
I'm not aware of any general approach to only using the basename, but
you can use -gcflags=-trimpath=/Users/nyenin/dev/src to trim off a
consistent prefix.

Ian

Marvin Renich

unread,
Jun 5, 2016, 3:49:03 PM6/5/16
to golan...@googlegroups.com
* Ian Lance Taylor <ia...@golang.org> [160605 13:49]:
> On Sat, Jun 4, 2016 at 8:15 AM, 'Nikita Yenin' via golang-nuts wrote:
> > Hi, Is it possible to eliminate printing of the complete path to the source
> > code when a program panics? Any options that can be used during go build or
> > go install?
> >
> > For e.g... Can "/Users/nyenin/dev/src/errorf.go:10" be simply "errorf.go:10"
> >
> > Sample run of a program that hit a panic.
> >
> > goroutine 1 [running]:
> >
> > panic(0xb8300, 0xc82006c1e0)
> >
> > /usr/local/go/src/runtime/panic.go:481 +0x3e6
> >
> > main.printer(0x0, 0x0, 0x0, 0x0)
> >
> > /Users/nyenin/dev/src/errorf.go:19 +0x91
> >
> > main.main()
> >
> > /Users/nyenin/dev/src/errorf.go:10 +0x127
> >
> > exit status 2
>
> I'm not aware of any general approach to only using the basename, but
> you can use -gcflags=-trimpath=/Users/nyenin/dev/src to trim off a
> consistent prefix.

Perhaps go build and go install by default could add an appropriate
-trimpath to remove the portion of the path corresponding to the element
of GOPATH for each compiled file. That should allow reproducible builds
and keep enough info to find the source file (in most cases).

...Marvin

Nikita Yenin

unread,
Jun 5, 2016, 8:49:27 PM6/5/16
to Marvin Renich, golan...@googlegroups.com
Thank you everyone for the suggestions, the following works for my needs.

go install -gcflags=-trimpath=$GOPATH
or
go build -gcflags=-trimpath=$GOPATH



--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.




as....@gmail.com

unread,
Jun 5, 2016, 11:34:42 PM6/5/16
to golang-nuts, nikit...@protonmail.com
There at least one way to do this at runtime, but it seems ugly and unreliable. 

https://play.golang.org/p/_Le2bLymHK

There's also an interesting case of panic writing to an arbitrary file after os.Stderr. is closed.

The original idea I had was to swap some os.File referring to standard error with a pair of file pipes that process the output of a panic, eg:

defer func() {
    err := recover()
    os.Stderr, f := f, os.Stderr   // f piped through user-defined writer
    panic(err)
}    
panic("test")

The above didn't work; panic uses low level printing and runtime/write_err.go references fd 2 directly.  That gave me another idea: To suppress panic output completely, can't we just close fd 2 through os.Stderr.Close() ? 

Turns out this is a bad idea. The next file I create with os.Create() gets fd 2, and the next panic writes to this file instead of os.Stderr. 

https://play.golang.org/p/D2mIGkI4Oo

This example doesn't work on the playground, but I tested it with go1.7beta1 on plan9/amd64 and go1.6.2 linux/arm. It remains to be determined what happens on windows.


On Saturday, June 4, 2016 at 11:35:43 PM UTC-7, Nikita Yenin wrote:

Nikita Yenin

unread,
Jun 6, 2016, 12:15:51 AM6/6/16
to Steve Phillips, golang-nuts
I am using 1.6.2 and the following works in eliminating the path that i want to suppress in the panic messages.

go install -gcflags=-trimpath=$GOPATH
or
go build -gcflags=-trimpath=$GOPATH


Konstantin Khomoutov

unread,
Jun 6, 2016, 7:35:27 AM6/6/16
to Nikita Yenin, 'Nikita Yenin' via golang-nuts, Marvin Renich
On Sun, 05 Jun 2016 20:49:15 -0400
"'Nikita Yenin' via golang-nuts" <golan...@googlegroups.com> wrote:

> Thank you everyone for the suggestions, the following works for my
> needs.
>
> go install -gcflags=-trimpath=$GOPATH
> or
> go build -gcflags=-trimpath=$GOPATH
[...]

Note that the GOPATH env. variable is perfectly able to contain several
pathnames separated by the platform-specific separator (':' in your
case, I beleive).

Hence the first iteration at having a more robust solution whould be
using something liks

go install -gcflags=-trimpath=${GOPATH%%:*}

(See [1] for more info.)

On the second thought, as support for multiple workspaces means the
source of each package used to build the resulting executable could
have been picked from any workspace listed in $GOPATH, any approach
which blindly uses the value of that variable is fragile (and is
just incorrect from a theoretical standpoint.)

I suggest you to read the output of `go help gopath` to get full
explanations of the semantics of the gc's support for workspaces.

1. http://pubs.opengroup.org/onlinepubs/009604499/utilities/xcu_chap02.html#tag_02_06_02

Marvin Renich

unread,
Jun 6, 2016, 10:27:44 AM6/6/16
to golan...@googlegroups.com
* Marvin Renich <mr...@renich.org> [160605 15:48]:
> Perhaps go build and go install by default could add an appropriate
> -trimpath to remove the portion of the path corresponding to the element
> of GOPATH for each compiled file. That should allow reproducible builds
> and keep enough info to find the source file (in most cases).

* Konstantin Khomoutov <flat...@users.sourceforge.net> [160606 07:35]:
> On the second thought, as support for multiple workspaces means the
> source of each package used to build the resulting executable could
> have been picked from any workspace listed in $GOPATH, any approach
> which blindly uses the value of that variable is fragile (and is
> just incorrect from a theoretical standpoint.)
[I know you were responding to the OP, but even if you weren't alluding
to my msg, I believe the following is relevant.]

First, I am not a reproducible-builds enthusiast, but I know that, at
least in the Debian community, there is an active and growing effort to
support reproducible builds, and they have some significant benefits,
which is why I made my suggestion.

From a theoretical standpoint, removing GOPATH elements loses
information, but it is not "incorrect". Even the current situation does
not give complete enough information to uniquely identify the exact
source used, such as the machine on which the source was built or the
current SC revision checked out.

From the standpoint of reproducible builds, however, it is expected that
the executable is built from publicly available source, which means the
import path, and thus the part of the file name remaining after removing
GOPATH elements, is unique enough, and just as informative as the
current full path.

The go tools are not the Go language, and don't need to be
"theoretically perfect". The defaults should be what works best in most
situations, as long as there is a way to override those defaults. In
most realistic situations that do not involve reproducible builds,
removing leading GOPATH elements will not cause any problem, but for
reproducible builds, doing so has significant benefits. This is why I
believe my suggestion is worth consideration.

Reproducible builds are not important enough to me to continue to
champion this suggestion if there is opposition to it, but I didn't want
it dismissed as "fragile" (which is not true in a realistic build
environment) or "incorrect" (which is simply, ah, incorrect). (And,
yes, I have two elements in my GOPATH.)

...Marvin

Aram Hăvărneanu

unread,
Jun 6, 2016, 10:37:57 AM6/6/16
to Marvin Renich, golang-nuts
On Mon, Jun 6, 2016 at 4:27 PM, Marvin Renich <mr...@renich.org> wrote:
> In
> most realistic situations that do not involve reproducible builds,
> removing leading GOPATH elements will not cause any problem

Of course they cause a problem. They are a PITA for development. As a
developer, I don't want merely *a* mapping between panic message and
source code, I want *the* mapping that helps me find the source code
with minimum amount of effort. That particular mapping is the one that
prints the full path to the source.

People have development tooling, e.g. plumb(1), acme(1) that uses this
particular type of information. I literally just click on a path and
it opens the file at the correct line number in my editor.

If this mapping were more complex than that, programs would have to be
changed, or some other kind of intermediate transformation system
(a.i. more work) would have to be implemented to keep the current
workflow going.

Reproductible builds are a very good idea for distributors, and I hope
they do it, and Go should easily support it, but it is not true that
having it on in development would not be costly on the developer.

--
Aram Hăvărneanu

Konstantin Khomoutov

unread,
Jun 6, 2016, 10:49:11 AM6/6/16
to Marvin Renich, golan...@googlegroups.com
On Mon, 6 Jun 2016 10:27:29 -0400
Marvin Renich <mr...@renich.org> wrote:

[...]
> Reproducible builds are not important enough to me to continue to
> champion this suggestion if there is opposition to it, but I didn't
> want it dismissed as "fragile" (which is not true in a realistic build
> environment) or "incorrect" (which is simply, ah, incorrect). (And,
> yes, I have two elements in my GOPATH.)

I'm pretty sure you overreacted.

My line of reasoning was simple:

* The OP posts what he thinks is a solution to his problem.

* I see a problem with that approach and make that clear --
so the OP is aware of the possible repercussions of what
he's doing. Even if the OP is fully aware of the fact the gc
toolchain is able to pull the modules from different workspaces,
I thought it was necessary to annotate the OP's findings for
the next guy who will stumble on it via google search.

As to reproducible builds, I'm fully with you on this question
(being involved in Debian as well, BTW) but it's pretty tangential
to the aim of my mail which was to prevent a possible problem for the
OP or someone else reading his post, not to bash the idea of having
more sensible debug data. So we really have no point of contention ;-)

Marvin Renich

unread,
Jun 6, 2016, 11:29:24 AM6/6/16
to golan...@googlegroups.com
* Konstantin Khomoutov <flat...@users.sourceforge.net> [160606 10:49]:
> On Mon, 6 Jun 2016 10:27:29 -0400
> Marvin Renich <mr...@renich.org> wrote:
> > Reproducible builds are not important enough to me to continue to
> > champion this suggestion if there is opposition to it, but I didn't
> > want it dismissed as "fragile" (which is not true in a realistic build
> > environment) or "incorrect" (which is simply, ah, incorrect). (And,
> > yes, I have two elements in my GOPATH.)
>
> I'm pretty sure you overreacted.

I didn't mean it to sound that way, and I apologize if it did. I simply
didn't want my suggestion dismissed as part of "any approach which
blindly uses the value of that variable". The significant amount of
assistance you give to others on this list is very much appreciated.

I also have to concede the point made by Aram Hăvărneanu about tools
that assist the user in locating the offending source code line.

> My line of reasoning was simple:
[good stuff snipped]

Okay.

...Marvin

Reply all
Reply to author
Forward
0 new messages