HaxeFoundation / HaxeFoundation/haxe

[eval] Missing SO_REUSEADDR when binding socket

Open
#12,880 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
Haxe
Stars
6.9k
Forks
715
Avg merge
2d 2h
Merged PRs (30d)
11

Description

In Neko, HashLink, and hxcpp, `SO_REUSEADDR` flag is set on the socket when calling the `bind()` method.

https://github.com/HaxeFoundation/neko/blob/v2-4-1/libs/std/socket.c#L559
https://github.com/HaxeFoundation/hashlink/blob/1.15/src/std/socket.c#L284
https://github.com/HaxeFoundation/hxcpp/blob/v4.3.140/src/hx/libs/std/Socket.cpp#L810

As best I can tell, the Haxe eval interpreter does not use this flag:

https://github.com/HaxeFoundation/haxe/blob/4.3.7/src/macro/eval/evalStdLib.ml#L2039

I'm running into an issue where it frequently is throwing the following exception when I exit the server and start it again. I don't see the same issue with the other mentioned targets, and I believe that it is because of this flag.

```
Unix.Unix_error(Unix.EADDRINUSE, "bind", "")
```

I'm trying to write a simple HTTP server that can run in the Haxe interpreter. My goal is to give developers the ability to spin up a simple development server using Haxe only, without requiring a separate tool like Node.js, Python, PHP, etc.

I can reproduce on my machine with the following code:

```haxe
import sys.net.Host;
import sys.net.Socket;

class Main {
static function main() {
var socket = new Socket();
socket.bind(new Host("127.0.0.1"), 8000);
socket.listen(10);
while (true) {
var client = socket.accept();
while (true) {
var line = client.input.readLine();
if (line.length == 0) {
break;
}
}
var body = "

404 Not Found

";
var response = "HTTP/1.0 404 Not Found\r\n"
+ "Content-Type: text/html\r\n"
+ 'Content-Length: ${body.length}\r\n'
+ "\r\n"
+ body;
client.output.writeString(response);
client.close();
}
}
}
```

Steps:

1. Run `haxe --interp --main Main` in a terminal.
2. Switch to a web browser, and load `http://127.0.0.1:8000` (not sure why this step is necessary).
3. Back in the terminal, use Ctrl+C to stop the server.
4. Run `haxe --interp --main Main` again.

The second attempt at starting the server will typically result in the `Unix.Unix_error(Unix.EADDRINUSE, "bind", "")` exception on my Linux machine. I originally observed this same behavior on macOS several months ago. Usually, after a couple of minutes, it will stop throwing the exception, and binding the socket will succeed again.

As mentioned above, Neko, HL, and C++ targets allow the socket to bind immediately instead of having to wait a bit.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.