Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api/bytes.html
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ <h3 class="function-name">from_ptr <span class="kind">fn</span></h3>
<h3 class="function-name">string_from_ptr <span class="kind">fn</span></h3>
<pre class="usage"><code>string_from_ptr(src, length) <span class="arrow">-&gt;</span> string</code></pre>
<p class="signature"><span class="sig-params">src: ptr, length: int</span></p>
<p class="doc">One-call ptr -&gt; string crossing: a fresh refcounted binary string copying `length` bytes from a raw pointer `src`, without an intermediate bytes. The direct answer to &quot;I have a ptr + len, I want a string&quot; (issue #1782).</p>
<p class="doc">One-call ptr -&gt; string crossing: a fresh refcounted binary string copying `length` bytes from a raw pointer `src`, without an intermediate bytes. The direct answer to &quot;I have a ptr + len, I want a string&quot; (issue #1782). `src` must be a RAW data pointer: `bytes.data(b)` or a C buffer. A bytes handle is also a `ptr` but is refused (panic): for a handle use `bytes.to_string(b, n)`.</p>
</div>
<div class="function" id="view" data-name="view">
<h3 class="function-name">view <span class="kind">fn</span></h3>
Expand Down
4 changes: 3 additions & 1 deletion docs/api/http.html
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ <h3 class="function-name">server_port <span class="kind">extern</span></h3>
<h3 class="function-name">server_start_raw <span class="kind">extern</span></h3>
<pre class="usage"><code>server_start_raw(server) <span class="arrow">-&gt;</span> int</code></pre>
<p class="signature"><span class="sig-params">server: ptr</span></p>
<p class="doc">A start of a server that is already running is refused (-1, the reason in http_server_error).</p>
</div>
<div class="function" id="server_set_host" data-name="server_set_host">
<h3 class="function-name">server_set_host <span class="kind">fn</span></h3>
Expand All @@ -467,6 +468,7 @@ <h3 class="function-name">server_start_background_raw <span class="kind">extern<
<h3 class="function-name">server_stop <span class="kind">extern</span></h3>
<pre class="usage"><code>server_stop(server)</code></pre>
<p class="signature"><span class="sig-params">server: ptr</span></p>
<p class="doc">Stop waits until the server's run is over, whichever start began it and on whatever thread, so a free may follow at once. On one of the server's own threads (a handler, the monitor) it only signals, and a free there is fatal: free it from the thread that started it.</p>
</div>
<div class="function" id="server_free" data-name="server_free">
<h3 class="function-name">server_free <span class="kind">extern</span></h3>
Expand Down Expand Up @@ -795,7 +797,7 @@ <h3 class="function-name">server_start <span class="kind">fn</span></h3>
</div>
<div class="function" id="server_start_background" data-name="server_start_background">
<h3 class="function-name">server_start_background <span class="kind">fn</span></h3>
<pre class="usage"><code>server_start_background(server) <span class="arrow">-&gt;</span> string</code></pre>
<pre class="usage"><code>server_start_background(server)</code></pre>
<p class="signature"><span class="sig-params">server: ptr</span></p>
<p class="doc">Start a server on a detached native thread. Useful for integration tests and embedding hosts that need multiple local servers in one process without tying up the Aether actor scheduler.</p>
</div>
Expand Down
18 changes: 14 additions & 4 deletions docs/http-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -913,17 +913,27 @@ any connection; a keep-alive connection waiting for its client's next
request, or parked, is closed at once rather than after its idle
timeout.

A stop waits for the server's run to be over, whichever start began it
and whichever thread it runs on (the caller's for `server_start`, an
actor's, or the server's own for `server_start_background`): when
`http_server_stop` returns, the accept loop, its workers and the
parking lot are done, so the server can be freed at once, or started
again. Called on one of the server's own threads (a handler, the
monitor), a stop cannot wait for a run that waits for that thread, so
it only signals, and the run ends once the call returns;
`http_server_free` there is a fatal error, since the run still uses
the server: free it from the thread that started it, whose own stop
waits. A start of a server that is already running is refused, with
the reason in `http_server_error`.

---

## Embedded / background servers

`http_server_start_background_raw(server)` runs the accept loop on a
thread of its own and returns immediately, so a host can keep serving
while doing other work (and stop it later with `http_server_stop`).
Stop waits for that thread: when it returns, the accept loop, its
workers and the parking lot are done, so the server can be freed at
once, and another started in the same process. This is the *embedded*
mode and behaves like a library, not a CLI:
This is the *embedded* mode and behaves like a library, not a CLI:

- **No banner.** It has no monitor unless the program gives it one, so
it prints nothing: an embedded server is controlled by
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- **`http_server_stop` waits for a foreground server too, so a free after it
is safe.** Stop waited only for a server started with
`http_server_start_background_raw`. A foreground `http_server_start_raw`
run on another thread (an actor's) was signalled and left running, and the
`http_server_free` that followed released it under its accept loop and a
pool worker still serving a keep-alive connection: a segfault in
`conn_recv_request_start` / `http_resolve_route` on macOS and Linux (found
by servirtium-vcr). Now a stop waits until the run is over, whichever start
began it. On one of the server's own threads (a handler, the monitor, an
HTTP/2 dispatch worker, the proxy driver's middleware) it only signals,
since the run waits for that thread: a background server stopped from a
handler used to hang there. `http_server_free` on such a thread while the
server runs is a fatal error rather than a use after free, and a start of
a running server is refused with the reason in `http_server_error`.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **`ae build` on macOS no longer prints an `ld: warning` for every Homebrew dylib it links.** With `MACOSX_DEPLOYMENT_TARGET` unset, the toolchain targeted the installed SDK's macOS, which can trail the running OS; Homebrew builds its dylibs for the running OS, so each link of a program using nghttp2 (or any newer-built dylib) warned "building for macOS-27.0, but linking with dylib ... built for newer version 27.2", and the warning landed in the output of `ae run`. A native `ae build` now defaults the deployment target to the running OS; a `MACOSX_DEPLOYMENT_TARGET` you set still wins, and cross builds are unchanged. `ae cflags --libs` adds the same `-mmacosx-version-min=` for a build that drives its own compiler.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **`bytes.string_from_ptr` refuses a bytes handle instead of copying its header** (`std/bytes/aether_bytes.c`, `std/bytes/module.ae`). `string_from_ptr(src, n)` wants a raw data pointer (`bytes.data(b)` or a C buffer), but a bytes handle is also a `ptr`, so `bytes.string_from_ptr(b, 4)` compiled and silently returned the `AetherBytes` struct header as text (it produced garbage keys in servirtium-vcr's Azure Key Vault test). `AetherBytes` now carries an 8-byte tag (cleared on free) and `string_from_ptr` panics on a live handle with a message naming `bytes.to_string(b, n)` and `bytes.data(b)`; the check reads one byte of a raw buffer unless the tag matches, so short C buffers are never over-read. The module comment, `std/bytes/README.md` and `docs/api` say `src` must be a raw data pointer. Test: `tests/regression/test_bytes_string_from_ptr_handle.ae` (the handle is refused; `to_string` and `string_from_ptr(bytes.data(b), n)` stay binary-safe over NUL and 0xff).
8 changes: 7 additions & 1 deletion std/bytes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ There is deliberately no `ptr as string` cast (they are different types).

```aether,fragment
// ptr -> string (I have a raw buffer + length, I want a binary string)
s = bytes.string_from_ptr(p, n)
s = bytes.string_from_ptr(p, n) // p: bytes.data(b) or a C buffer, NOT a bytes handle

// string -> ptr (I have a string, I want a raw pointer to walk)
n = string.length(s)
Expand All @@ -52,6 +52,12 @@ p = bytes.data(b)
// ... use p ... (keep `b` alive as long as you use `p`)
```

`src` must be a raw data pointer. A bytes handle is also a `ptr`, so the
compiler cannot tell the two apart, but `string_from_ptr` recognises a handle
and panics rather than copy its header as text. To turn a handle into a
string use `bytes.to_string(b, n)`; to use the handle's payload as a raw
pointer, `bytes.string_from_ptr(bytes.data(b), n)`.

The longhand still works and is useful when you build a buffer incrementally:

```aether,fragment
Expand Down
32 changes: 32 additions & 0 deletions std/bytes/aether_bytes.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions std/bytes/module.ae
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ from_ptr(src: ptr, length: int) -> ptr {
// One-call ptr -> string crossing: a fresh refcounted binary string copying
// `length` bytes from a raw pointer `src`, without an intermediate bytes.
// The direct answer to "I have a ptr + len, I want a string" (issue #1782).
// `src` must be a RAW data pointer: `bytes.data(b)` or a C buffer. A bytes
// handle is also a `ptr` but is refused (panic): for a handle use
// `bytes.to_string(b, n)`.
string_from_ptr(src: ptr, length: int) -> string {
return aether_bytes_string_from_ptr(src, length)
}
Expand Down
8 changes: 7 additions & 1 deletion std/http/module.ae
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,14 @@ extern http_server_port(server: ptr) -> int
// loopback binds. A host name binds the IPv4 address it resolves to,
// and one that does not resolve fails the bind (#2639).
extern http_server_set_host(server: ptr, host: string)
// A start of a server that is already running is refused (-1, the reason in
// http_server_error).
extern http_server_start_raw(server: ptr) -> int
extern http_server_start_background_raw(server: ptr) -> int
// Stop waits until the server's run is over, whichever start began it and on
// whatever thread, so a free may follow at once. On one of the server's own
// threads (a handler, the monitor) it only signals, and a free there is fatal:
// free it from the thread that started it.
extern http_server_stop(server: ptr)
extern http_server_free(server: @frees ptr)
// TLS termination (#260 Tier 0). Loads the cert+key (PEM-encoded);
Expand Down Expand Up @@ -872,7 +878,7 @@ server_start(server: ptr) -> {
server_start_background(server: ptr) -> {
rc = http_server_start_background_raw(server)
if rc < 0 {
return "server background start failed"
return server_error_or(server, "server background start failed")
}
return ""
}
Expand Down
6 changes: 5 additions & 1 deletion std/http/server/h2/aether_h2.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions std/net/aether_http_evloop.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions std/net/aether_http_pool.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading