Skip to content

Commit

Permalink
compiler/natives/src/internal/poll: Create no-op I/O poller implement…
Browse files Browse the repository at this point in the history
…ation.

gopherjs test uses tempFile to create temporary files during execution
of examples. tempFile calls os.OpenFile to create a file. os.OpenFile
calls newFile, which in Go 1.9 tries to add the file to the runtime
poller.

Normally, on OSes like darwin, linux, etc., this tries to use a real
runtime poller from internal/poll package. We override that package
so that a no-op implementation (based on NaCL implementation) is used
instead.

Fixes:

	Error: runtime error: native function not implemented: internal/poll.runtime_pollServerInit

After this change, some basic tests pass:

	$ gopherjs test errors github.com/gopherjs/gopherjs/tests
	PASS
	ok  	errors	0.453s
	PASS
	ok  	github.com/gopherjs/gopherjs/tests	0.606s
  • Loading branch information
dmitshur committed Jun 24, 2017
1 parent 88d1ca5 commit 3fc24d9
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 3 deletions.
23 changes: 20 additions & 3 deletions build/build.go
Expand Up @@ -93,13 +93,15 @@ func importWithSrcDir(path string, srcDir string, mode build.ImportMode, install

switch path {
case "os":
pkg.GoFiles = stripExecutable(pkg.GoFiles) // Need to strip executable implementation files, because some of them contain package scope variables that perform (indirectly) syscalls on init.
pkg.GoFiles = excludeExecutable(pkg.GoFiles) // Need to exclude executable implementation files, because some of them contain package scope variables that perform (indirectly) syscalls on init.
case "runtime":
pkg.GoFiles = []string{"error.go"}
case "runtime/internal/sys":
pkg.GoFiles = []string{fmt.Sprintf("zgoos_%s.go", buildContext.GOOS), "zversion.go"}
case "runtime/pprof":
pkg.GoFiles = nil
case "internal/poll":
pkg.GoFiles = exclude(pkg.GoFiles, "fd_poll_runtime.go")
case "crypto/rand":
pkg.GoFiles = []string{"rand.go", "util.go"}
case "crypto/x509":
Expand Down Expand Up @@ -131,9 +133,9 @@ func importWithSrcDir(path string, srcDir string, mode build.ImportMode, install
return &PackageData{Package: pkg, JSFiles: jsFiles}, nil
}

// stripExecutable strips all executable implementation .go files.
// excludeExecutable excludes all executable implementation .go files.
// They have "executable_" prefix.
func stripExecutable(goFiles []string) []string {
func excludeExecutable(goFiles []string) []string {
var s []string
for _, f := range goFiles {
if strings.HasPrefix(f, "executable_") {
Expand All @@ -144,6 +146,21 @@ func stripExecutable(goFiles []string) []string {
return s
}

// exclude returns files, excluding specified files.
func exclude(files []string, exclude ...string) []string {
var s []string
Outer:
for _, f := range files {
for _, e := range exclude {
if f == e {
continue Outer
}
}
s = append(s, f)
}
return s
}

// ImportDir is like Import but processes the Go package found in the named
// directory.
func ImportDir(dir string, mode build.ImportMode, installSuffix string, buildTags []string) (*PackageData, error) {
Expand Down
52 changes: 52 additions & 0 deletions compiler/natives/src/internal/poll/fd_poll_js.go
@@ -0,0 +1,52 @@
// +build js

package poll

import "time"

// pollDesc is a no-op implementation of an I/O poller for GOARCH=js.
type pollDesc struct {
closing bool
}

func (pd *pollDesc) init(fd *FD) error { return nil }

func (pd *pollDesc) close() {}

func (pd *pollDesc) evict() { pd.closing = true }

func (pd *pollDesc) prepare(mode int, isFile bool) error {
if pd.closing {
return errClosing(isFile)
}
return nil
}

func (pd *pollDesc) prepareRead(isFile bool) error { return pd.prepare('r', isFile) }

func (pd *pollDesc) prepareWrite(isFile bool) error { return pd.prepare('w', isFile) }

func (pd *pollDesc) wait(mode int, isFile bool) error {
if pd.closing {
return errClosing(isFile)
}
return ErrTimeout
}

func (pd *pollDesc) waitRead(isFile bool) error { return pd.wait('r', isFile) }

func (pd *pollDesc) waitWrite(isFile bool) error { return pd.wait('w', isFile) }

func (*pollDesc) waitCanceled(mode int) {}

func (*FD) SetDeadline(t time.Time) error { return nil }

func (*FD) SetReadDeadline(t time.Time) error { return nil }

func (*FD) SetWriteDeadline(t time.Time) error { return nil }

// PollDescriptor returns the descriptor being used by the poller,
// or ^uintptr(0) if there isn't one. This is only used for testing.
func PollDescriptor() uintptr {
return ^uintptr(0)
}

0 comments on commit 3fc24d9

Please sign in to comment.