1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
// contract.reef — illumos process contract FFI bindings
//
// Provides Reef wrappers around libcontract for managing service processes.
// Process contracts are an illumos kernel feature — this module ONLY works
// on illumos/Hammerhead.
//
// Reference: illumos libcontract(3LIB), contract(5), process(5)
// Source reference: hammerhead/usr/src/cmd/svc/startd/contract.c
// C FFI declarations for libcontract
extern "C" {
// Template management
fn ct_tmpl_activate(fd: i32) -> i32;
fn ct_tmpl_clear(fd: i32) -> i32;
fn ct_tmpl_set_informative(fd: i32, events: u32) -> i32;
fn ct_tmpl_set_critical(fd: i32, events: u32) -> i32;
// Process contract template
fn ct_pr_tmpl_set_fatal(fd: i32, events: u32) -> i32;
fn ct_pr_tmpl_set_param(fd: i32, params: u32) -> i32;
// Contract status
fn ct_status_read(fd: i32, detail: i32, statp: *mut CtStatus) -> i32;
fn ct_status_free(status: *mut CtStatus);
fn ct_status_get_id(status: *CtStatus) -> i32;
// Contract control
fn ct_ctl_abandon(fd: i32) -> i32;
fn ct_ctl_adopt(fd: i32) -> i32;
// POSIX
fn open(path: *const u8, flags: i32) -> i32;
fn close(fd: i32) -> i32;
fn fork() -> i32;
fn execvp(file: *const u8, argv: *const *const u8) -> i32;
fn setsid() -> i32;
fn sigsend(idtype: i32, id: i64, sig: i32) -> i32;
fn poll(fds: *mut PollFd, nfds: i32, timeout: i32) -> i32;
}
// Contract event flags
const CT_PR_EV_EMPTY: u32 = 0x01; // all processes exited
const CT_PR_EV_FORK: u32 = 0x02; // process forked
const CT_PR_EV_EXIT: u32 = 0x04; // process exited
const CT_PR_EV_CORE: u32 = 0x08; // process dumped core
const CT_PR_EV_SIGNAL: u32 = 0x10; // fatal signal
const CT_PR_EV_HWERR: u32 = 0x20; // hardware error
// Contract parameter flags
const CT_PR_INHERIT: u32 = 0x01; // inherit contract on fork
const CT_PR_NOORPHAN: u32 = 0x02; // kill orphans on contract abandon
// Contract template path
const CTFS_PROCESS_TEMPLATE: &str = "/system/contract/process/template";
const CTFS_PROCESS_LATEST: &str = "/system/contract/process/latest";
const CTFS_PROCESS_BUNDLE: &str = "/system/contract/process/bundle";
// Managed contract handle
struct Contract {
id: i32, // contract ID from kernel
service_name: String,
bundle_fd: i32, // fd for event monitoring
}
// Set up a contract template for forking a service
fn setup_template() -> Result<i32, String> {
// TODO: implement
// 1. open(CTFS_PROCESS_TEMPLATE, O_RDWR)
// 2. ct_tmpl_set_informative(fd, CT_PR_EV_EMPTY)
// 3. ct_tmpl_set_critical(fd, CT_PR_EV_EMPTY | CT_PR_EV_HWERR)
// 4. ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR)
// 5. ct_pr_tmpl_set_param(fd, CT_PR_INHERIT | CT_PR_NOORPHAN)
// 6. ct_tmpl_activate(fd)
// 7. Return fd
Err("not yet implemented")
}
// After fork(), retrieve the contract ID for the new child
fn get_latest_contract() -> Result<i32, String> {
// TODO: implement
// 1. open(CTFS_PROCESS_LATEST, O_RDONLY)
// 2. ct_status_read()
// 3. ct_status_get_id()
// 4. Return contract ID
Err("not yet implemented")
}
// Open the contract bundle fd for poll()-based event monitoring
fn open_bundle() -> Result<i32, String> {
// TODO: implement
Err("not yet implemented")
}
// Kill all processes in a contract
fn kill_contract(contract_id: i32, signal: i32) -> Result<(), String> {
// TODO: implement using sigsend(P_CTID, contract_id, signal)
Err("not yet implemented")
}
// Re-adopt an existing contract (after zyginit restart)
fn adopt_contract(contract_id: i32) -> Result<(), String> {
// TODO: implement
Err("not yet implemented")
}
|