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

Distinguish failures to sync stdout and stderr on Linux #370

Closed
akshayjshah opened this issue Mar 13, 2017 · 2 comments
Closed

Distinguish failures to sync stdout and stderr on Linux #370

akshayjshah opened this issue Mar 13, 2017 · 2 comments

Comments

@akshayjshah
Copy link
Contributor

Reworded and migrated from #328. Whenever logging messages that may crash the program, zap attempts to sync all open WriteSyncers. Briefly, the issue is that os.Stdout and os.Stderr don't reliably support syncing - on Linux, they return EINVAL. Ideally, we'd only ignore sync errors from these special files on Linux.

However, that's error-prone and difficult to test thoroughly. Instead, we're currently ignoring all sync errors - users can't do anything about failures to sync stderr and stdout, other files are unlikely to fail syncs but accept writes, and other WriteSyncer implementations can provide their own observability hooks.

Details

The issue here is that fsync behaves differently on OSX and Linux. When doing a Fatal, zap calls Sync on os.Stdout, which ends up calling fsync.

The documentation for fsync specifies that EINVAL may be returned depending on the type of file passed in, but does not explicitly call out whether it will work for stdout. The Linux documentation says:

       EROFS, EINVAL
              fd is bound to a special file which does not support synchronization.

The OSX documentation is similar:

     [EINVAL]           fildes refers to a file type (e.g., a socket) that does not support this operation.

This simple example reproduces the issue with fsync behaving differently:

$ cat main.go
package main

import (
	"fmt"
	"os"
)

func main() {
	fmt.Println(os.Stdout.Sync())
}

OSX:

$ uname -a
Darwin prashant-[...] 15.6.0 Darwin Kernel Version 15.6.0: Mon Jan  9 23:07:29 PST 2017; root:xnu-3248.60.11.2.1~1/RELEASE_X86_64 x86_64


$ go run main.go
<nil>

Linux:

$ uname -a
Linux [..] 4.4.27 #1 SMP Sun Oct 23 18:20:55 UTC 2016 x86_64 GNU/Linux
$ go run main.go
fsync: invalid argument
akshayjshah pushed a commit that referenced this issue Mar 14, 2017
Take the simplest approach to fixing the cross-platform compatibility issues with syncing stderr and stdout (outlined in #328) and just ignore sync errors. If we come up with a clean solution to #370, we can revert this change.
@akshayjshah
Copy link
Contributor Author

akshayjshah commented Jun 8, 2017

In (actually) thrilling news, newer versions of OS X also don't support syncing stdout.

@akshayjshah
Copy link
Contributor Author

Since we don't actually have plans to fix this, I'm going to close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

1 participant