Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MacOS Big Sur "open" command no error response #46542

Closed
Stoyvo opened this issue Jun 3, 2021 · 10 comments
Closed

MacOS Big Sur "open" command no error response #46542

Stoyvo opened this issue Jun 3, 2021 · 10 comments

Comments

@Stoyvo
Copy link

Stoyvo commented Jun 3, 2021

What version of Go are you using (go version)?

$ go version
go version go1.16.4 darwin/amd64

Description of Issue

For a typical oauth flow from a distributed application, a web browser (users default) would open and user can authenticate. When the "open" command is executed with the "exec" package, there is no error response and there is no web browser opened. This appears to be a permission issue on Big Sur.

One possible solution is to code-sign and allow accessibility to the application, but this doesn't work for development purposes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/stoyvo/Library/Caches/go-build"
GOENV="/Users/stoyvo/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/stoyvo/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/stoyvo/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.16.4"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/stoyvo/Development/stoyvo.com/bigsuropen/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/47/0r5gtz6x44981kyqt77x80f00000gn/T/go-build379743986=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

err = exec.Command("open", url).Start()
if err != nil {
	log.Println(err)
}

What did you expect to see?

Expected log entry.

What did you see instead?

No error response returned, however web browser does not open (permission issue?)

@seankhliao
Copy link
Member

This appears to be a question about development on MacOS

Unlike many projects, the Go project does not use GitHub Issues for general discussion or asking questions. GitHub Issues are used for tracking bugs and proposals only.

For questions please refer to https://github.com/golang/go/wiki/Questions

@Stoyvo
Copy link
Author

Stoyvo commented Jun 3, 2021

@seankhliao The programming language returns no error message. You're stating that this is not a Go issue, and it's strictly an OS issue? Remember, this works in terminal. If the programming language cannot accurately return an error state, then what's the point of the error response?

@Stoyvo
Copy link
Author

Stoyvo commented Jun 3, 2021

Taking a look at the Fyne.io implementation: https://github.com/fyne-io/fyne/blob/d85af0115040a05096191c1f55c2f8330f9349df/app/app_darwin.go#L49

There is additional handling for Go by assigning OS error output (since Go doesn't accurately return error response).

The response is:

exit status 1

Definitely a permission issue that is uncaught.

@seankhliao
Copy link
Member

I don't see any additional handling? It uses app.exec which is just os/exec.Command

@AlexRouSg
Copy link
Contributor

@Stoyvo you are calling cmd.Start, this does not return the error code as it does not wait for the program to exit, so it can only report errors with starting the program.
To get the return code you need to cmd.Wait()

Or to do it in one line, use cmd.Run(), which fyne.io is also using.

@Stoyvo
Copy link
Author

Stoyvo commented Jun 3, 2021

@AlexRouSg Yes this is a good callout. I did change to .Run() and there is still no error message...

However, there is a CONSOLE output.

		cmd := exec.Command("/usr/bin/open", url)
                cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr // This line creates CONSOLE output
                err = cmd.Run()
                if err != nil {
                        log.Println(err)
                }

In the code above, there is no content to "err" variable (no message in the log.Println), but if you're watching run/debug console there is an error.

In my specific situation there is an unescaped character that breaks the "open" command (must be a change in Big Sur command arguments):
Error visible in CONSOLE (not log.Println):

The file /Users/stoyvo/Development/stoyvo.com/bigsuropen/https:/google.com/ does not exist.

The MacOS Big Sur is breaking the URL structure.

I'm still at a loss why exec.Command("open", "https:/ /google.com/").Run() returns no error response, and instead I MUST use: "cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr" before calling .Run().

I still strongly believe that exec package should report OS failures with commands, otherwise how does the developer know the command failed? It's obviously achievable by defining the os.Stdout and os.Stderr.

@randall77
Copy link
Contributor

When you run open <your url> on the command line, then do echo $?, what does it print?
I'm wondering whether Go is not collecting the error code properly, or whether open is not reporting that there was an error.

Can you be more specific about what url you're working with? It's hard for us to reproduce without giving us a full program that's failing.

@Stoyvo
Copy link
Author

Stoyvo commented Jun 3, 2021

Here is a usable example:

package main

import (
        "fmt"
        "os/exec"
)

func main() {
        cmd := exec.Command("/usr/bin/open", "https://google.com/?unescaped=1 2 3 4") // Bad URL
        err := cmd.Run()
        if err != nil {
                fmt.Println("err:", err)
        }
}

Output:

err: exit status 1

This error is not helpful. Now, lets modify our function:

package main

import (
        "fmt"
        "os"
        "os/exec"
)

func main() {
        cmd := exec.Command("/usr/bin/open", "https://google.com/?unescaped=1 2 3 4") // Bad URL
        cmd.Stdin, cmd.Stdout, cmd.Stderr = os.Stdin, os.Stdout, os.Stderr
        err := cmd.Run()
        if err != nil {
                fmt.Println("err:", err)
        }
}

Output:

The file /Users/stoyvo/Development/stoyvo.com/bigsuropen/https:/google.com/?unescaped=1 2 3 4 does not exist.
err: exit status 1

Why should "exec" not return the cause of "exit status 1"?

@seankhliao
Copy link
Member

That's what os/exec.ExitError is for https://pkg.go.dev/os/exec#ExitError

@randall77
Copy link
Contributor

It looks like the ExitError that is returned doesn't have its Stderr field filled in if you use Wait (or things that use wait internally, like Run). You need to use Output.

@bradfitz who wrote the capture code in Output in https://go-review.googlesource.com/c/go/+/11415 . Can Wait also fill in the Stderr field?

@golang golang locked and limited conversation to collaborators Jun 3, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants