Skip to content

SOCK_NONBLOCK / SOCK_CLOEXEC syscall issues #1148

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

Closed
omar391 opened this issue Sep 14, 2022 · 4 comments
Closed

SOCK_NONBLOCK / SOCK_CLOEXEC syscall issues #1148

omar391 opened this issue Sep 14, 2022 · 4 comments

Comments

@omar391
Copy link

omar391 commented Sep 14, 2022

Running a sample socket code throws the following syscall issues:

package main
import "github.com/gofiber/fiber/v2"

func main() {
	app := fiber.New()

	app.Get("/get", func(c *fiber.Ctx) error {
		return c.SendString("Hello from GET!")
	})

	app.Post("/post", func(c *fiber.Ctx) error {
		return c.SendString("Hello from POST!")
	})

	_ = app.Listen(":3000")
}

Error:

../../../github.com/valyala/tcplisten@v1.0.0/socket_other.go:11:48: SOCK_NONBLOCK not declared by package syscall
../../../github.com/valyala/tcplisten@v1.0.0/socket_other.go:11:70: SOCK_CLOEXEC not declared by package syscall

GopherJS version:

GopherJS 1.18.0+go1.18.5

Build cmd:

GOOS=js GOARCH=ecmascript gopherjs build main.go

@nevkontakte
Copy link
Member

@omar391 starting with 1.18 version, GopherJS builds standard library in the same way that Go WebAssembly does, and these constants are unavailable there. That said, to my knowledge GopherJS never properly supported server-side networking.

I'm curious why not use native Go if you are building something server-side?

@omar391
Copy link
Author

omar391 commented Sep 24, 2022

@nevkontakte, Thanks for the reply but GopherJs has a more complete syscall pkg using node-syscall (https://github.com/gopherjs/gopherjs/tree/master/node-syscall) than Go's Js pkg.

Based on the readme:

2021-06-19: Complete syscall/js package implementation compatible with the upstream Go 1.16.

So, to answer your last ques, it's only relevant that we expect to run our Go code in a NodeJS environment.

From my experiment, I was able to compile one of Go's HTTP libs. But failed to run fiber's code due to those 2 syscall variables being not present in the node-syscall pkg.

My expectation is that, if we can import these(+remaining) LIBC variables in node-syscall pkg then we can run all Go's server code in a Nodejs environment.

@nevkontakte
Copy link
Member

I think you might be mixing up a few different things, so let me try and clarify.

  • syscall and syscall/js packages are completely different API serving different purposes, they are not interchangeable.
    • syscall provides access to platform-specific kernel system calls, by necessity it has very different APIs for different GOOS values. Naturally, in a browser environment it wouldn't work because there is no access to OS kernel.
    • syscall/js provides access to the raw JavaScript environment for Go WebAssembly programs. GopherJS doesn't use WebAssembly, but our runtime environment is close enough that we could fully support syscall/js API on top of our own github.com/gopherjs/gopherjs/js package. This is what the README line you've cited is about.
  • node-syscall module was originally invented to enable things line file system access when using GopherJS with NodeJS, where you could potentially have access to system calls. However, that led to a whole host of long-term issues for the project, which you can read about in Standardize on a single GOOS/GOARCH and deprecate node-syscall module. #1111 and proposal: Limit support to one GOOS value (primarily for stdlib). #693. Since GopherJS 1.18 it is considered deprecated and we are now using NodeJS's APIs to emulate a subset of syscalls, such as file system access or process argv. Has an up to date summary for the state of syscall support: https://github.com/gopherjs/gopherjs/blob/master/doc/syscalls.md.

The problem you are encountering is due to github.com/valyala/tcplisten package expecting GOOS=linux variant of the syscall package, whereas GopherJS provides GOOS=js one, regardless of what GOOS is used for non-standard-library code. One option you potentially have is to contribute GopherJS/Wasm support to the tcplisten package, which would do its thing using syscall/js and NodeJS's APIs, instead of OS syscalls.

Even then, you are not necessarily out of weeds. GOOS=js variant of the net package builds, but it doesn't provide a real TCP stack support. It uses an in-process fake implementation, which is used mainly to pass the tests. To the best of my knowledge, nobody has tried to use GopherJS to do server-side networking, so here be dragons. It's not unachievable, but it will be quite a bit of work, if I were to guess.

So if you can tell me more about the actual problem you are trying to solve, I may be able to give you a more helpful advice. If using native Go is not an option for you because you need to integrate with some pre-existing NodeJS code, it may be better for you to use a NodeJS server framework (express.js or similar), and export Go functions into the JS environment as JS functions (that is something GopherJS can do). Or do the opposite, and use native Go and https://github.com/dop251/goja to run JS bits you need.

@flimzy
Copy link
Member

flimzy commented May 14, 2025

This issue hasn't seen any activity in a couple years, so I'm going to close it. If there's anything outstanding that needs to be addressed, please reply, and I'd love to re-open this.

@flimzy flimzy closed this as completed May 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants