mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-17 15:34:54 +00:00
dev_alloc built its buffer with vec!, which allocates on the path that cannot fail: a valid layout the allocator refuses goes to handle_alloc_error, and that aborts. An abort is not a panic, so the catch_unwind around it never ran. dev_alloc(isize::MAX) died on SIGABRT, taking every other session in the process with it, and the same call into dev.wasm trapped on unreachable — under a doc and a header that both promised null. Ask the allocator directly. Layout::from_size_align refuses a length with no layout, alloc_zeroed answers null when there is no memory, and nothing left in there can panic, so the catch_unwind goes. dev_release frees the buffer as the boxed [u8] whose layout this is. The module doc and dev.h now say how far "the process stays up" reaches: a panic, and no further. Memory the library needs for itself still aborts when refused — with the module's memory lent out, a dev_step on a 512 MiB input traps — and dev_alloc is the one place a refusal comes back. The test asks for isize::MAX bytes and the two lengths past it; against the old body it kills the test binary with SIGABRT, and so does the C fixture asking for PTRDIFF_MAX through dev.h. The wasm import list is unchanged. Co-authored-by: Hanzo Dev <[email protected]>
89 lines
3.5 KiB
C
89 lines
3.5 KiB
C
/* The C ABI of the dev agent loop (HIP-1330).
|
|
*
|
|
* Written by hand and kept beside crates/ffi/src/lib.rs, which the C ABI test
|
|
* in crates/ffi/tests/abi.c compiles against the staticlib. There is no
|
|
* generator step to forget to run.
|
|
*
|
|
* Ownership:
|
|
* - Every pointer you pass in is copied before the call returns.
|
|
* - Every dev_buf handed back is a Rust allocation; release it with
|
|
* dev_free and never with free(3).
|
|
* - A session handle is opaque and generational: dev_drop retires it, and a
|
|
* retired handle answers DEV_HANDLE instead of naming a live session. A
|
|
* dev_drop that lands while a call on that session is running makes the
|
|
* call answer DEV_HANDLE and hand back no dev_buf: there is no session
|
|
* left for its answer to belong to.
|
|
* - A call that panics answers DEV_PANIC and poisons that session; its later
|
|
* calls answer DEV_POISON until dev_drop. Other sessions are untouched.
|
|
* - A refused allocation is not a panic. Memory the library needs for itself
|
|
* and is refused ends the process, or in wasm traps the instance; dev_alloc
|
|
* is the one place a refusal comes back, as a null.
|
|
* - A dev_buf is written only on DEV_OK. On any other status the out
|
|
* parameter is left as the caller passed it.
|
|
*
|
|
* Payloads are dev-protocol messages (Config, Event, Action list, snapshot) in
|
|
* the encoding dev_abi() names.
|
|
*/
|
|
|
|
#ifndef HANZO_DEV_H
|
|
#define HANZO_DEV_H
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#define DEV_OK 0 /* the call did what it was asked */
|
|
#define DEV_HANDLE (-1) /* the handle names no live session */
|
|
#define DEV_MALFORMED (-2) /* the payload is not a message of this protocol */
|
|
#define DEV_POISON (-3) /* a previous call on this session panicked */
|
|
#define DEV_PANIC (-4) /* this call panicked; the session is now poisoned */
|
|
#define DEV_NULL (-5) /* a pointer the caller must supply was null */
|
|
#define DEV_BUSY (-6) /* the session is inside another call */
|
|
#define DEV_FULL (-7) /* no slot is left for another session */
|
|
|
|
/* A byte string Rust owns until dev_free. */
|
|
typedef struct dev_buf {
|
|
uint8_t *ptr;
|
|
size_t len;
|
|
size_t cap;
|
|
} dev_buf;
|
|
|
|
/* Version of this ABI and of the payload encoding behind it. */
|
|
uint32_t dev_abi(void);
|
|
|
|
/* Start a session from an encoded Config, or from the default when len is 0.
|
|
* Writes the handle to out. */
|
|
int32_t dev_new(const uint8_t *cfg, size_t len, uint64_t *out);
|
|
|
|
/* Feed one encoded Event; writes the encoded action list to out. */
|
|
int32_t dev_step(uint64_t session, const uint8_t *event, size_t len, dev_buf *out);
|
|
|
|
/* Write the session's snapshot to out. */
|
|
int32_t dev_snapshot(uint64_t session, dev_buf *out);
|
|
|
|
/* Rebuild a session from a snapshot; writes its new handle to out. */
|
|
int32_t dev_restore(const uint8_t *state, size_t len, uint64_t *out);
|
|
|
|
/* End a session and retire its handle. */
|
|
void dev_drop(uint64_t session);
|
|
|
|
/* Release a dev_buf this library handed out. */
|
|
void dev_free(dev_buf buf);
|
|
/* Lend the host len zeroed bytes inside this library's memory; null for a zero
|
|
* len or a refused allocation. Compiled to wasm the library's memory is its own,
|
|
* so a host there has no other way to produce an input pointer or an
|
|
* out-parameter. A native host shares an address space and never needs it. */
|
|
uint8_t *dev_alloc(size_t len);
|
|
/* Take back what dev_alloc lent. ptr and len are that call's answer and its
|
|
* argument. */
|
|
void dev_release(uint8_t *ptr, size_t len);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* HANZO_DEV_H */
|