Keep FastCGI available during restarts
This commit is contained in:
parent
93c701c6c7
commit
caffb3f404
@ -145,6 +145,25 @@ module lives in the configured writable cache root rather than beside the
|
||||
possibly root-owned deployed `core.wasm`; freshness still uses the deployed
|
||||
artifact's metadata.
|
||||
|
||||
Packaged deployments use systemd socket activation for FastCGI. The socket unit
|
||||
owns `/run/uce/fastcgi.sock`; UCE validates and adopts the single named listener
|
||||
after exec. The listener therefore remains connectable and queues requests while
|
||||
the service and its post-fork workers restart. Direct launches without systemd
|
||||
activation retain the existing configured Unix/TCP listener behavior.
|
||||
On termination the parent asks render workers to close their listeners, finish
|
||||
accepted connections within the bounded worker drain interval, and only then
|
||||
exits. This prevents an accepted FastCGI request from being reset at handoff;
|
||||
the socket unit queues later connections for the replacement workers.
|
||||
The graceful signal handler belongs to the parent and render workers. Generic
|
||||
`task()` children restore default termination signals after fork so
|
||||
`task_kill()` and `server_stop()` retain their immediate stop contract.
|
||||
|
||||
Epoch interruption measures uninterrupted guest CPU segments. The common
|
||||
hostcall membrane re-arms the store deadline after every native call, excluding
|
||||
blocking I/O, process waits, hashing, and other host work without weakening a
|
||||
guest loop that makes no hostcalls. Keeping this at the membrane also covers new
|
||||
hostcalls without per-import timeout bookkeeping.
|
||||
|
||||
`request_perf()` reports worker module-cache hits and misses and divides a miss
|
||||
into artifact lookup, wasm read, custom-section parse, serialized-module
|
||||
deserialization or wasm compilation, and immutable import classification. This
|
||||
|
||||
@ -4,7 +4,8 @@ set -e
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl daemon-reload >/dev/null 2>&1 || true
|
||||
if [ "$1" = "configure" ]; then
|
||||
systemctl enable uce.service >/dev/null 2>&1 || true
|
||||
systemctl enable uce.socket uce.service >/dev/null 2>&1 || true
|
||||
systemctl start uce.socket >/dev/null 2>&1 || true
|
||||
systemctl restart uce.service >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -3,7 +3,7 @@ set -e
|
||||
|
||||
if [ "$1" = "remove" ] || [ "$1" = "deconfigure" ]; then
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl disable --now uce.service >/dev/null 2>&1 || true
|
||||
systemctl disable --now uce.service uce.socket >/dev/null 2>&1 || true
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
[Unit]
|
||||
Description=UCE FastCGI Runtime
|
||||
After=network-online.target mariadb.service memcached.service
|
||||
After=network-online.target mariadb.service memcached.service uce.socket
|
||||
Wants=network-online.target
|
||||
Requires=uce.socket
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
@ -10,12 +11,10 @@ RuntimeDirectory=uce
|
||||
StateDirectory=uce
|
||||
CacheDirectory=uce
|
||||
ExecStartPre=/usr/bin/mkdir -p /var/cache/uce/work /var/lib/uce/uploads /var/lib/uce/sessions
|
||||
ExecStartPre=/usr/bin/rm -f /run/uce/fastcgi.sock
|
||||
ExecStart=/usr/lib/uce/bin/uce_fastcgi.linux.bin
|
||||
ExecStopPost=/usr/bin/rm -f /run/uce/fastcgi.sock
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
TimeoutStopSec=15
|
||||
TimeoutStopSec=30
|
||||
KillMode=mixed
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
15
scripts/deb/uce.socket
Normal file
15
scripts/deb/uce.socket
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=UCE FastCGI socket
|
||||
|
||||
[Socket]
|
||||
ListenStream=/run/uce/fastcgi.sock
|
||||
FileDescriptorName=fastcgi
|
||||
SocketUser=www-data
|
||||
SocketGroup=www-data
|
||||
SocketMode=0660
|
||||
DirectoryMode=0755
|
||||
Backlog=100
|
||||
Service=uce.service
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
@ -205,6 +205,7 @@ bundle_wasmtime "$STAGE_DIR"
|
||||
|
||||
write_packaged_settings "$STAGE_DIR/etc/uce/settings.cfg" "$WEBROOT"
|
||||
install -m 0644 "$DEB_ASSET_DIR/uce.service" "$STAGE_DIR/lib/systemd/system/uce.service"
|
||||
install -m 0644 "$DEB_ASSET_DIR/uce.socket" "$STAGE_DIR/lib/systemd/system/uce.socket"
|
||||
install -m 0644 "$DEB_ASSET_DIR/conffiles" "$DEBIAN_DIR/conffiles"
|
||||
install -m 0755 "$DEB_ASSET_DIR/postinst" "$DEBIAN_DIR/postinst"
|
||||
install -m 0755 "$DEB_ASSET_DIR/prerm" "$DEBIAN_DIR/prerm"
|
||||
|
||||
@ -179,6 +179,7 @@ bundle_wasi_sdk "$STAGE_DIR"
|
||||
bundle_wasmtime "$STAGE_DIR"
|
||||
write_packaged_settings "$STAGE_DIR/etc/uce/settings.cfg" "$WEBROOT"
|
||||
install -m 0644 "$REPO_ROOT/scripts/deb/uce.service" "$STAGE_DIR/usr/lib/systemd/system/uce.service"
|
||||
install -m 0644 "$REPO_ROOT/scripts/deb/uce.socket" "$STAGE_DIR/usr/lib/systemd/system/uce.socket"
|
||||
|
||||
(
|
||||
cd "$STAGE_DIR"
|
||||
@ -225,13 +226,14 @@ cp -a %{_builddir}/$PACKAGE_NAME-$VERSION/. %{buildroot}/
|
||||
%post
|
||||
if command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl daemon-reload >/dev/null 2>&1 || true
|
||||
systemctl enable uce.service >/dev/null 2>&1 || true
|
||||
systemctl enable uce.socket uce.service >/dev/null 2>&1 || true
|
||||
systemctl start uce.socket >/dev/null 2>&1 || true
|
||||
systemctl restart uce.service >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
%preun
|
||||
if [ "\$1" = "0" ] && command -v systemctl >/dev/null 2>&1; then
|
||||
systemctl disable --now uce.service >/dev/null 2>&1 || true
|
||||
systemctl disable --now uce.service uce.socket >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
%postun
|
||||
@ -245,6 +247,7 @@ fi
|
||||
%config(noreplace) /etc/uce/settings.cfg
|
||||
/usr/lib/uce
|
||||
/usr/lib/systemd/system/uce.service
|
||||
/usr/lib/systemd/system/uce.socket
|
||||
$WEBROOT
|
||||
%dir /var/cache/uce
|
||||
%dir /var/lib/uce
|
||||
|
||||
@ -73,4 +73,5 @@ if [[ "$action" == "run" ]]; then
|
||||
scripts/test_mysql_epoch_refresh.sh
|
||||
scripts/test_mysql_persistent_pool.sh
|
||||
scripts/test_log_timeliness.sh
|
||||
scripts/test_socket_activation.sh
|
||||
fi
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
[Unit]
|
||||
Description=UCE FastCGI Runtime
|
||||
After=network-online.target mariadb.service memcached.service
|
||||
After=network-online.target mariadb.service memcached.service uce.socket
|
||||
Wants=network-online.target
|
||||
Requires=uce.socket
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
@ -10,13 +11,11 @@ RuntimeDirectory=uce
|
||||
StateDirectory=uce
|
||||
CacheDirectory=uce
|
||||
ExecStartPre=/usr/bin/mkdir -p /var/cache/uce/work /var/lib/uce/uploads /var/lib/uce/sessions
|
||||
ExecStartPre=/usr/bin/rm -f /run/uce/fastcgi.sock
|
||||
ExecStartPre=/usr/bin/bash /Code/uce.openfu.com/uce/scripts/build_linux.sh
|
||||
ExecStart=/Code/uce.openfu.com/uce/bin/uce_fastcgi.linux.bin
|
||||
ExecStopPost=/usr/bin/rm -f /run/uce/fastcgi.sock
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
TimeoutStopSec=15
|
||||
TimeoutStopSec=30
|
||||
KillMode=mixed
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
15
scripts/systemd/uce.socket
Normal file
15
scripts/systemd/uce.socket
Normal file
@ -0,0 +1,15 @@
|
||||
[Unit]
|
||||
Description=UCE FastCGI socket
|
||||
|
||||
[Socket]
|
||||
ListenStream=/run/uce/fastcgi.sock
|
||||
FileDescriptorName=fastcgi
|
||||
SocketUser=www-data
|
||||
SocketGroup=www-data
|
||||
SocketMode=0660
|
||||
DirectoryMode=0755
|
||||
Backlog=100
|
||||
Service=uce.service
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
38
scripts/test_socket_activation.sh
Executable file
38
scripts/test_socket_activation.sh
Executable file
@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
service_name="${UCE_TEST_SERVICE:-uce.service}"
|
||||
socket_name="${UCE_TEST_SOCKET_SERVICE:-uce.socket}"
|
||||
http_host="${UCE_TEST_HTTP_HOST:-uce.openfu.com}"
|
||||
http_path="${UCE_TEST_HTTP_PATH:-/info/}"
|
||||
requests="${UCE_TEST_RESTART_REQUESTS:-100}"
|
||||
statuses=$(mktemp)
|
||||
trap 'rm -f "$statuses"' EXIT
|
||||
|
||||
systemctl is-active --quiet "$socket_name"
|
||||
systemctl is-active --quiet "$service_name"
|
||||
socket_path=$(systemctl show -p Listen --value "$socket_name" | sed -n 's/ \+(Stream)$//p')
|
||||
[[ -S "$socket_path" ]]
|
||||
inode_before=$(stat -c %i "$socket_path")
|
||||
|
||||
(
|
||||
for ((i = 0; i < requests; i++)); do
|
||||
curl -sS --max-time 15 -o /dev/null -w '%{http_code}\n' \
|
||||
-H "Host: $http_host" "http://127.0.0.1${http_path}"
|
||||
done
|
||||
) >"$statuses" &
|
||||
load_pid=$!
|
||||
sleep 0.05
|
||||
systemctl restart "$service_name"
|
||||
wait "$load_pid"
|
||||
|
||||
inode_after=$(stat -c %i "$socket_path")
|
||||
[[ "$inode_after" = "$inode_before" ]]
|
||||
[[ $(wc -l <"$statuses") -eq "$requests" ]]
|
||||
if [[ $(grep -c '^200$' "$statuses") -ne "$requests" ]]; then
|
||||
sort "$statuses" | uniq -c >&2
|
||||
exit 1
|
||||
fi
|
||||
systemctl is-active --quiet "$socket_name"
|
||||
systemctl is-active --quiet "$service_name"
|
||||
echo "socket activation restart passed across $requests HTTP requests"
|
||||
@ -206,7 +206,6 @@ FastCGIServer::shutdown()
|
||||
{
|
||||
printf("Closing server socket %i\n", *it);
|
||||
close(*it);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::iterator it = listen_unlink.begin();
|
||||
@ -223,7 +222,6 @@ FastCGIServer::shutdown()
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
server_sockets.clear();
|
||||
|
||||
}
|
||||
@ -264,6 +262,22 @@ FastCGIServer::listen(unsigned tcp_port)
|
||||
return(listen(tcp_port, "0.0.0.0"));
|
||||
}
|
||||
|
||||
int
|
||||
FastCGIServer::adopt_listener(int socket_handle, char type)
|
||||
{
|
||||
int accepting = 0;
|
||||
socklen_t accepting_size = sizeof(accepting);
|
||||
if(socket_handle < 0 || getsockopt(socket_handle, SOL_SOCKET, SO_ACCEPTCONN,
|
||||
&accepting, &accepting_size) != 0 || !accepting)
|
||||
throw std::runtime_error("inherited descriptor is not a listening socket");
|
||||
set_socket_nonblocking(socket_handle);
|
||||
server_sockets.push_back(socket_handle);
|
||||
server_socket_types[socket_handle] = type;
|
||||
printf("(P) adopted #%i inherited %s listener\n", socket_handle,
|
||||
type == 'F' ? "FastCGI" : "server");
|
||||
return(socket_handle);
|
||||
}
|
||||
|
||||
int
|
||||
FastCGIServer::listen(unsigned tcp_port, const std::string& bind_address)
|
||||
{
|
||||
|
||||
@ -57,6 +57,7 @@ public:
|
||||
int listen_http(unsigned tcp_port, const std::string& bind_address);
|
||||
int listen_cli(const std::string& local_path);
|
||||
int listen(const std::string& local_path);
|
||||
int adopt_listener(int socket_handle, char type = 'F');
|
||||
|
||||
void process(int timeout_ms = -1); // timeout_ms<0 blocks forever
|
||||
void process_forever();
|
||||
|
||||
@ -1549,6 +1549,12 @@ pid_t task(String key, std::function<void()> exec_after_spawn, u64 timeout)
|
||||
{
|
||||
close_locked_file(lock_fd);
|
||||
my_pid = getpid();
|
||||
// The FastCGI worker handles termination to drain accepted requests.
|
||||
// Generic task children do not run that drain loop, so inheriting those
|
||||
// handlers would turn task_kill(SIGTERM) into a no-op.
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGINT, SIG_DFL);
|
||||
signal(SIGHUP, SIG_DFL);
|
||||
signal(SIGALRM, SIG_DFL);
|
||||
if(timeout > 0)
|
||||
alarm(timeout);
|
||||
|
||||
@ -699,15 +699,7 @@ volatile bool termination_signal_received = false;
|
||||
|
||||
void on_terminate(int sig)
|
||||
{
|
||||
if(termination_signal_received)
|
||||
return;
|
||||
termination_signal_received = true;
|
||||
if(getpid() != parent_pid)
|
||||
exit(1);
|
||||
printf("Terminating... PID %i:%i\n", getpid(), parent_pid);
|
||||
wasm_backend_shutdown();
|
||||
server.shutdown();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void clear_shared_unit_cache(ServerState& state)
|
||||
@ -1069,7 +1061,7 @@ void run_ws_broker()
|
||||
ws_broker.listen(server_state.config["WS_BROKER_SOCKET_PATH"]);
|
||||
chmod(server_state.config["WS_BROKER_SOCKET_PATH"].c_str(), S_IRWXU | S_IRGRP | S_IWGRP);
|
||||
}
|
||||
for(;;)
|
||||
while(!termination_signal_received)
|
||||
{
|
||||
ws_broker.process(50);
|
||||
ws_broker_drain_outbound(ws_broker_outbound_timeout_seconds);
|
||||
@ -1254,7 +1246,7 @@ void run_proactive_compiler()
|
||||
}
|
||||
next_scan_at = time_precise();
|
||||
|
||||
for(;;)
|
||||
while(!termination_signal_received)
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -1397,10 +1389,21 @@ void listen_for_connections()
|
||||
printf("(P) wasm worker ready: PID %i in %.3f ms\n", getpid(), wasm_ms);
|
||||
else
|
||||
fprintf(stderr, "(!) wasm worker initialization failed: PID %i in %.3f ms: %s\n", getpid(), wasm_ms, wasm_error.c_str());
|
||||
for(;;)
|
||||
while(!termination_signal_received)
|
||||
{
|
||||
server.process(-1);
|
||||
}
|
||||
close_inherited_server_sockets();
|
||||
f64 drain_deadline = time_precise() + (f64)to_u64(server_state.config["WORKER_DRAIN_TIMEOUT_SECONDS"], 10);
|
||||
while(!server.client_sockets.empty() && time_precise() < drain_deadline)
|
||||
server.process(100);
|
||||
if(!server.client_sockets.empty())
|
||||
fprintf(stderr, "(!) worker PID %i drain deadline reached with %zu client connections\n",
|
||||
getpid(), server.client_sockets.size());
|
||||
else
|
||||
printf("(P) worker PID %i drained cleanly\n", getpid());
|
||||
wasm_backend_shutdown();
|
||||
exit(server.client_sockets.empty() ? 0 : 1);
|
||||
}
|
||||
|
||||
mode_t configured_socket_mode(String value, mode_t fallback)
|
||||
@ -1424,6 +1427,25 @@ void chmod_configured_socket(String path, String mode_value, mode_t fallback)
|
||||
fprintf(stderr, "(!) Could not chmod socket %s to %04o: %s\n", path.c_str(), (unsigned int)mode, strerror(errno));
|
||||
}
|
||||
|
||||
int systemd_fastcgi_listener()
|
||||
{
|
||||
const char* listen_pid = getenv("LISTEN_PID");
|
||||
const char* listen_fds = getenv("LISTEN_FDS");
|
||||
if(!listen_pid || !listen_fds)
|
||||
return(-1);
|
||||
if(to_u64(listen_pid, 0) != (u64)getpid())
|
||||
return(-1);
|
||||
if(to_u64(listen_fds, 0) != 1)
|
||||
throw std::runtime_error("UCE requires exactly one systemd FastCGI listener");
|
||||
const char* names = getenv("LISTEN_FDNAMES");
|
||||
if(names && names[0] != '\0' && String(names) != "fastcgi")
|
||||
throw std::runtime_error("systemd listener must be named fastcgi");
|
||||
unsetenv("LISTEN_PID");
|
||||
unsetenv("LISTEN_FDS");
|
||||
unsetenv("LISTEN_FDNAMES");
|
||||
return(3);
|
||||
}
|
||||
|
||||
StringMap redacted_server_config_for_log(const StringMap& config)
|
||||
{
|
||||
StringMap redacted = config;
|
||||
@ -1443,13 +1465,16 @@ void init_base_process()
|
||||
server_state.config = make_server_settings();
|
||||
server_state.config["COMPILER_SYS_PATH"] = cwd_get();
|
||||
printf("Compiler base path: %s\n", server_state.config["COMPILER_SYS_PATH"].c_str());
|
||||
int inherited_fastcgi = systemd_fastcgi_listener();
|
||||
if(inherited_fastcgi >= 0)
|
||||
server.adopt_listener(inherited_fastcgi, 'F');
|
||||
|
||||
if(server_state.config["FCGI_PORT"] != "")
|
||||
server.listen(int_val(server_state.config["FCGI_PORT"]));
|
||||
|
||||
printf("%s\n", var_dump(redacted_server_config_for_log(server_state.config)).c_str());
|
||||
|
||||
if(server_state.config["FCGI_SOCKET_PATH"] != "")
|
||||
if(inherited_fastcgi < 0 && server_state.config["FCGI_SOCKET_PATH"] != "")
|
||||
{
|
||||
server.listen(server_state.config["FCGI_SOCKET_PATH"]);
|
||||
chmod_configured_socket(server_state.config["FCGI_SOCKET_PATH"], server_state.config["FCGI_SOCKET_MODE"], 0666);
|
||||
@ -1469,7 +1494,9 @@ void init_base_process()
|
||||
mkdir(server_state.config["SESSION_PATH"]);
|
||||
|
||||
signal(SIGCHLD, on_child_exit);
|
||||
signal(SIGTERM, on_terminate);
|
||||
signal(SIGINT, on_terminate);
|
||||
signal(SIGHUP, on_terminate);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
srand(time());
|
||||
}
|
||||
@ -1489,7 +1516,7 @@ int main(int argc, char** argv)
|
||||
ensure_proactive_compiler();
|
||||
ensure_ws_broker();
|
||||
|
||||
for(;;)
|
||||
while(!termination_signal_received)
|
||||
{
|
||||
if(!proactive_compiler_alive())
|
||||
proactive_compiler_pid = 0;
|
||||
@ -1512,5 +1539,22 @@ int main(int argc, char** argv)
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
printf("(P) draining %zu workers before shutdown\n", workers.size());
|
||||
for(auto& worker : workers)
|
||||
kill(worker.first, SIGTERM);
|
||||
if(proactive_compiler_pid > 0)
|
||||
kill(proactive_compiler_pid, SIGTERM);
|
||||
if(ws_broker_pid > 0)
|
||||
kill(ws_broker_pid, SIGTERM);
|
||||
f64 drain_deadline = time_precise() + (f64)to_u64(server_state.config["WORKER_DRAIN_TIMEOUT_SECONDS"], 10);
|
||||
while(!workers.empty() && time_precise() < drain_deadline)
|
||||
{
|
||||
on_child_exit(0);
|
||||
usleep(10000);
|
||||
}
|
||||
for(auto& worker : workers)
|
||||
kill(worker.first, SIGKILL);
|
||||
server.shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2106,6 +2106,11 @@ private:
|
||||
auto profiled = [self, callback, profile_name](Caller caller, Span<const Val> args, Span<Val> results) mutable -> Result<std::monostate, Trap> {
|
||||
auto started = std::chrono::steady_clock::now();
|
||||
auto result = callback(caller, args, results);
|
||||
// Epoch interruption limits guest CPU, not time spent in native I/O,
|
||||
// process management, hashing, or other host work. Re-arm at the one
|
||||
// membrane every hostcall crosses so newly added blocking imports
|
||||
// cannot silently consume the next guest segment's budget.
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
if(profile_name != "uce_host_request_perf")
|
||||
{
|
||||
u64 elapsed = (u64)std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - started).count();
|
||||
@ -2288,9 +2293,9 @@ private:
|
||||
if(mod == "env" && name == "uce_host_crypto_equal")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { String a,b; self->hostcall_read(args[0].i32(), args[1].i32(), a); self->hostcall_read(args[2].i32(), args[3].i32(), b); results[0]=Val((int32_t)(crypto_equal_native(a,b)?1:0)); return(std::monostate()); }));
|
||||
if(mod == "env" && name == "uce_host_password_hash")
|
||||
return(add([self](Caller caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { String password; self->hostcall_read(args[0].i32(), args[1].i32(), password); String out=password_hash_native(password); u32 cap=(u32)args[3].i32(); int32_t buf=args[2].i32(); if(buf&&cap>=out.size()) self->hostcall_write(buf,out); caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks); results[0]=Val((int32_t)out.size()); return(std::monostate()); }));
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { String password; self->hostcall_read(args[0].i32(), args[1].i32(), password); String out=password_hash_native(password); u32 cap=(u32)args[3].i32(); int32_t buf=args[2].i32(); if(buf&&cap>=out.size()) self->hostcall_write(buf,out); results[0]=Val((int32_t)out.size()); return(std::monostate()); }));
|
||||
if(mod == "env" && name == "uce_host_password_verify")
|
||||
return(add([self](Caller caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { String password,encoded; self->hostcall_read(args[0].i32(), args[1].i32(), password); self->hostcall_read(args[2].i32(), args[3].i32(), encoded); bool valid=password_verify_native(password,encoded); caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks); results[0]=Val((int32_t)(valid?1:0)); return(std::monostate()); }));
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { String password,encoded; self->hostcall_read(args[0].i32(), args[1].i32(), password); self->hostcall_read(args[2].i32(), args[3].i32(), encoded); bool valid=password_verify_native(password,encoded); results[0]=Val((int32_t)(valid?1:0)); return(std::monostate()); }));
|
||||
if(mod == "env" && name == "uce_host_password_needs_rehash")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { String encoded; self->hostcall_read(args[0].i32(), args[1].i32(), encoded); results[0]=Val((int32_t)(password_needs_rehash_native(encoded)?1:0)); return(std::monostate()); }));
|
||||
if(mod == "env" && name == "uce_host_log")
|
||||
@ -2316,7 +2321,6 @@ private:
|
||||
}
|
||||
if(buf != 0 && cap >= out.size())
|
||||
self->hostcall_write(buf, out);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0] = Val((int32_t)out.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
@ -2324,7 +2328,7 @@ private:
|
||||
return(add([self](Caller caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> {
|
||||
String encoded; self->hostcall_read(args[0].i32(), args[1].i32(), encoded); u32 cap=(u32)args[3].i32(); int32_t buf=args[2].i32(); String out; String stage_key="http:"+encoded;
|
||||
if(!self->hostcall_staged(stage_key,out)) { DValue req,response; String err; if(ucb_decode(encoded,req,&err)) response=uce_http_request_value(req); else response["error"]="http_request decode failed: "+err; out=ucb_encode(response); if(buf==0) self->hostcall_stage(stage_key,out); }
|
||||
if(buf&&cap>=out.size()) self->hostcall_write(buf,out); caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks); results[0]=Val((int32_t)out.size()); return(std::monostate());
|
||||
if(buf&&cap>=out.size()) self->hostcall_write(buf,out); results[0]=Val((int32_t)out.size()); return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_http_request_async")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { String encoded; self->hostcall_read(args[0].i32(), args[1].i32(), encoded); DValue req; String err; u64 id=0; if(ucb_decode(encoded,req,&err)) id=uce_http_spawn_spec(req); results[0]=Val((int64_t)id); return(std::monostate()); }));
|
||||
@ -2335,7 +2339,6 @@ private:
|
||||
String out; String stage_key="shell_dv:"+encoded;
|
||||
if(!self->hostcall_staged(stage_key,out)) { DValue spec, response; String err; if(ucb_decode(encoded,spec,&err)) response=uce_shell_exec_spec(spec); else response["error"]="shell_exec spec decode failed: "+err; out=ucb_encode(response); if(buf==0) self->hostcall_stage(stage_key,out); }
|
||||
if(buf&&cap>=out.size()) self->hostcall_write(buf,out);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0]=Val((int32_t)out.size()); return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_shell_spawn")
|
||||
@ -2347,7 +2350,7 @@ private:
|
||||
if(mod == "env" && name == "uce_host_job_result")
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { String out=ucb_encode(uce_job_result_value((u64)args[0].i64(), 100)); u32 cap=(u32)args[2].i32(); int32_t buf=args[1].i32(); if(buf&&cap>=out.size()) self->hostcall_write(buf,out); results[0]=Val((int32_t)out.size()); return(std::monostate()); }));
|
||||
if(mod == "env" && name == "uce_host_job_await")
|
||||
return(add([self](Caller caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { u64 timeout=std::min<u64>((u64)args[1].i64(), 30000); String out=ucb_encode(uce_job_result_value((u64)args[0].i64(), timeout)); u32 cap=(u32)args[3].i32(); int32_t buf=args[2].i32(); if(buf&&cap>=out.size()) self->hostcall_write(buf,out); caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks); results[0]=Val((int32_t)out.size()); return(std::monostate()); }));
|
||||
return(add([self](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { u64 timeout=std::min<u64>((u64)args[1].i64(), 30000); String out=ucb_encode(uce_job_result_value((u64)args[0].i64(), timeout)); u32 cap=(u32)args[3].i32(); int32_t buf=args[2].i32(); if(buf&&cap>=out.size()) self->hostcall_write(buf,out); results[0]=Val((int32_t)out.size()); return(std::monostate()); }));
|
||||
if(mod == "env" && name == "uce_host_job_cancel")
|
||||
return(add([](Caller, Span<const Val> args, Span<Val> results) -> Result<std::monostate, Trap> { results[0]=Val((int32_t)(uce_job_cancel_value((u64)args[0].i64())?1:0)); return(std::monostate()); }));
|
||||
if(mod == "env" && name == "uce_host_path_real")
|
||||
@ -2823,7 +2826,6 @@ private:
|
||||
}
|
||||
if(buf != 0 && cap >= out.size())
|
||||
self->hostcall_write(buf, out);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0] = Val((int32_t)out.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
@ -2922,7 +2924,6 @@ private:
|
||||
}
|
||||
if(buf != 0 && cap >= out.size())
|
||||
self->hostcall_write(buf, out);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0] = Val((int32_t)out.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
@ -3033,7 +3034,6 @@ private:
|
||||
}
|
||||
if(buf != 0 && cap >= out.size())
|
||||
self->hostcall_write(buf, out);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0] = Val((int32_t)out.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
@ -3074,7 +3074,6 @@ private:
|
||||
context->resources.sockets.push_back(fd);
|
||||
}
|
||||
results[0] = Val((int64_t)(fd > 0 ? fd : 0));
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
return(std::monostate());
|
||||
}));
|
||||
if(mod == "env" && name == "uce_host_socket_close")
|
||||
@ -3115,7 +3114,6 @@ private:
|
||||
}
|
||||
if(buf != 0 && cap >= out.size())
|
||||
self->hostcall_write(buf, out);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0] = Val((int32_t)out.size());
|
||||
return(std::monostate());
|
||||
}));
|
||||
@ -3208,7 +3206,6 @@ private:
|
||||
unsigned int remaining = ::sleep((unsigned int)(usec / 1000000ull));
|
||||
if(remaining != 0)
|
||||
{
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0] = Val((int32_t)remaining);
|
||||
return(std::monostate());
|
||||
}
|
||||
@ -3216,7 +3213,6 @@ private:
|
||||
}
|
||||
if(usec > 0)
|
||||
::usleep((useconds_t)usec);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
results[0] = Val((int32_t)0);
|
||||
return(std::monostate());
|
||||
}));
|
||||
@ -3275,7 +3271,6 @@ private:
|
||||
self->hostcall_write(args[6].i32(), resolved);
|
||||
}
|
||||
results[0] = Val(slot);
|
||||
caller.context().set_epoch_deadline(self->worker.cfg.epoch_deadline_ticks);
|
||||
return(std::monostate());
|
||||
}));
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user