From 3bca0809dc900737c9d093b3657fad690ba89e54 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 24 Apr 2024 16:52:01 +0800 Subject: [PATCH 1/2] Upgrade for new spawn --- contracts/spawn-callee/src/entry.rs | 7 +- contracts/spawn-callee/src/error.rs | 16 ++- contracts/spawn-caller/src/entry.rs | 46 ++++--- contracts/spawn-caller/src/error.rs | 16 ++- src/ckb_constants.rs | 18 ++- src/error.rs | 18 ++- src/high_level.rs | 39 ++---- src/syscalls/native.rs | 193 +++++++++++++++++++++------- 8 files changed, 238 insertions(+), 115 deletions(-) diff --git a/contracts/spawn-callee/src/entry.rs b/contracts/spawn-callee/src/entry.rs index 9297d95..0c13756 100644 --- a/contracts/spawn-callee/src/entry.rs +++ b/contracts/spawn-callee/src/entry.rs @@ -5,13 +5,14 @@ use ckb_std::syscalls; use core::result::Result; pub fn main() -> Result<(), Error> { - assert_eq!(syscalls::get_memory_limit(), 8); let argv = ckb_std::env::argv(); - ckb_std::debug!("argv: {:?}", argv); + let mut std_fds: [u64; 2] = [0; 2]; + syscalls::inherited_file_descriptors(&mut std_fds); let mut out = vec![]; for arg in argv { out.extend_from_slice(arg.to_bytes()); } - syscalls::set_content(&out)?; + let len = syscalls::write(std_fds[1], &out)?; + assert_eq!(len, 10); Ok(()) } diff --git a/contracts/spawn-callee/src/error.rs b/contracts/spawn-callee/src/error.rs index ce0bdeb..b78e033 100644 --- a/contracts/spawn-callee/src/error.rs +++ b/contracts/spawn-callee/src/error.rs @@ -7,9 +7,11 @@ pub enum Error { ItemMissing, LengthNotEnough, Encoding, - SpawnExceededMaxContentLength, - SpawnWrongMemoryLimit, - SpawnExceededMaxPeakMemory, + WaitFailure, + InvalidFd, + OtherEndClosed, + MaxVmsSpawned, + MaxFdsCreated, } impl From for Error { @@ -20,9 +22,11 @@ impl From for Error { ItemMissing => Self::ItemMissing, LengthNotEnough(_) => Self::LengthNotEnough, Encoding => Self::Encoding, - SpawnExceededMaxContentLength => Self::SpawnExceededMaxContentLength, - SpawnWrongMemoryLimit => Self::SpawnWrongMemoryLimit, - SpawnExceededMaxPeakMemory => Self::SpawnExceededMaxPeakMemory, + WaitFailure => Self::WaitFailure, + InvalidFd => Self::InvalidFd, + OtherEndClosed => Self::OtherEndClosed, + MaxVmsSpawned => Self::MaxVmsSpawned, + MaxFdsCreated => Self::MaxFdsCreated, Unknown(err_code) => panic!("unexpected sys error {}", err_code), } } diff --git a/contracts/spawn-caller/src/entry.rs b/contracts/spawn-caller/src/entry.rs index 2c7a2a2..24f99e3 100644 --- a/contracts/spawn-caller/src/entry.rs +++ b/contracts/spawn-caller/src/entry.rs @@ -6,22 +6,36 @@ use core::ffi::CStr; use core::result::Result; pub fn main() -> Result<(), Error> { - let arg1 = CStr::from_bytes_with_nul(b"hello\0").unwrap(); - let arg2 = CStr::from_bytes_with_nul(b"world\0").unwrap(); - - let mut spgs_exit_code: i8 = 0; - let mut spgs_content = [0u8; 80]; - let mut spgs_content_length: u64 = 80; - let spgs = syscalls::SpawnArgs { - memory_limit: 8, - exit_code: &mut spgs_exit_code as *mut i8, - content: &mut spgs_content as *mut u8, - content_length: &mut spgs_content_length as *mut u64, + let argc: u64 = 2; + let argv = { + let mut argv = alloc::vec![core::ptr::null(); argc as usize + 1]; + argv[0] = CStr::from_bytes_with_nul(b"hello\0").unwrap().as_ptr(); + argv[1] = CStr::from_bytes_with_nul(b"world\0").unwrap().as_ptr(); + argv + }; + let mut std_fds: [u64; 2] = [0, 0]; + let mut son_fds: [u64; 3] = [0, 0, 0]; + let (r0, w0) = syscalls::pipe()?; + std_fds[0] = r0; + son_fds[1] = w0; + let (r1, w1) = syscalls::pipe()?; + std_fds[1] = w1; + son_fds[0] = r1; + let mut pid: u64 = 0; + let mut spgs = syscalls::SpawnArgs { + argc: argc, + argv: argv.as_ptr(), + process_id: &mut pid as *mut u64, + inherited_fds: son_fds.as_ptr(), }; - let ret = syscalls::spawn(1, Source::CellDep, 0, &[arg1, arg2][..], &spgs); - assert!(ret == 0); - assert!(spgs_exit_code == 0); - let c_str = CStr::from_bytes_until_nul(&spgs_content).unwrap(); - assert_eq!(c_str.to_str().unwrap(), "helloworld"); + syscalls::spawn(1, Source::CellDep, 0, 0, &mut spgs)?; + let mut buf: [u8; 256] = [0; 256]; + let len = syscalls::read(std_fds[0], &mut buf)?; + assert_eq!(len, 10); + buf[len] = 0; + assert_eq!( + CStr::from_bytes_until_nul(&buf).unwrap().to_str().unwrap(), + "helloworld" + ); Ok(()) } diff --git a/contracts/spawn-caller/src/error.rs b/contracts/spawn-caller/src/error.rs index ce0bdeb..b78e033 100644 --- a/contracts/spawn-caller/src/error.rs +++ b/contracts/spawn-caller/src/error.rs @@ -7,9 +7,11 @@ pub enum Error { ItemMissing, LengthNotEnough, Encoding, - SpawnExceededMaxContentLength, - SpawnWrongMemoryLimit, - SpawnExceededMaxPeakMemory, + WaitFailure, + InvalidFd, + OtherEndClosed, + MaxVmsSpawned, + MaxFdsCreated, } impl From for Error { @@ -20,9 +22,11 @@ impl From for Error { ItemMissing => Self::ItemMissing, LengthNotEnough(_) => Self::LengthNotEnough, Encoding => Self::Encoding, - SpawnExceededMaxContentLength => Self::SpawnExceededMaxContentLength, - SpawnWrongMemoryLimit => Self::SpawnWrongMemoryLimit, - SpawnExceededMaxPeakMemory => Self::SpawnExceededMaxPeakMemory, + WaitFailure => Self::WaitFailure, + InvalidFd => Self::InvalidFd, + OtherEndClosed => Self::OtherEndClosed, + MaxVmsSpawned => Self::MaxVmsSpawned, + MaxFdsCreated => Self::MaxFdsCreated, Unknown(err_code) => panic!("unexpected sys error {}", err_code), } } diff --git a/src/ckb_constants.rs b/src/ckb_constants.rs index 8b2a684..18c714c 100644 --- a/src/ckb_constants.rs +++ b/src/ckb_constants.rs @@ -17,15 +17,23 @@ pub const SYS_LOAD_CELL_DATA_AS_CODE: u64 = 2091; pub const SYS_LOAD_CELL_DATA: u64 = 2092; pub const SYS_DEBUG: u64 = 2177; #[cfg(feature = "ckb2023")] -pub const SYS_SPAWN: u64 = 2101; +pub const SYS_SPAWN: u64 = 2601; #[cfg(feature = "ckb2023")] -pub const SYS_GET_MEMORY_LIMIT: u64 = 2102; +pub const SYS_WAIT: u64 = 2602; #[cfg(feature = "ckb2023")] -pub const SYS_SET_CONTENT: u64 = 2103; +pub const SYS_PROCESS_ID: u64 = 2603; #[cfg(feature = "ckb2023")] -pub const SYS_LOAD_BLOCK_EXTENSION: u64 = 2104; +pub const SYS_PIPE: u64 = 2604; +#[cfg(feature = "ckb2023")] +pub const SYS_WRITE: u64 = 2605; +#[cfg(feature = "ckb2023")] +pub const SYS_READ: u64 = 2606; #[cfg(feature = "ckb2023")] -pub const SYS_CURRENT_MEMORY: u64 = 2105; +pub const SYS_INHERITED_FD: u64 = 2607; +#[cfg(feature = "ckb2023")] +pub const SYS_CLOSE: u64 = 2608; +#[cfg(feature = "ckb2023")] +pub const SYS_LOAD_BLOCK_EXTENSION: u64 = 2104; pub const CKB_SUCCESS: u64 = 0; #[derive(Eq, PartialEq, Debug, Clone, Copy)] diff --git a/src/error.rs b/src/error.rs index bdc70ea..35b2c18 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,15 +10,21 @@ pub enum SysError { /// Data encoding error Encoding, + /// Failed to wait. Its value is 5. #[cfg(feature = "ckb2023")] - /// Content Length must be less than 256K. - SpawnExceededMaxContentLength, + WaitFailure, + /// Invalid file descriptor. Its value is 6. #[cfg(feature = "ckb2023")] - /// MemoryLimit is between 1 and 8. - SpawnWrongMemoryLimit, + InvalidFd, + /// Reading from or writing to file descriptor failed due to other end closed. Its value is 7. #[cfg(feature = "ckb2023")] - /// There is a maximum call depth limit by peak memory. - SpawnExceededMaxPeakMemory, + OtherEndClosed, + /// Max vms has been spawned. Its value is 8. + #[cfg(feature = "ckb2023")] + MaxVmsSpawned, + /// Max fds has been spawned. Its value is 9. + #[cfg(feature = "ckb2023")] + MaxFdsCreated, /// Unknown syscall error number Unknown(u64), diff --git a/src/high_level.rs b/src/high_level.rs index 0a92e2c..475413d 100644 --- a/src/high_level.rs +++ b/src/high_level.rs @@ -689,31 +689,20 @@ pub fn spawn_cell( code_hash: &[u8], hash_type: ScriptHashType, argv: &[&CStr], - memory_limit: u64, - content: &mut Vec, -) -> Result { + inherited_fds: &[u64], +) -> Result<(), SysError> { let index = look_for_dep_with_hash2(code_hash, hash_type)?; - let mut content_length = content.len() as u64; - let mut exit_code = 0i8; - let spgs = syscalls::SpawnArgs { - memory_limit, - exit_code: &mut exit_code as *mut i8, - content: content.as_mut_ptr(), - content_length: &mut content_length as *mut u64, - }; - let ret = syscalls::spawn(index, Source::CellDep, 0, argv, &spgs); - match ret { - 0 => { - content.truncate(content_length as usize); - Ok(exit_code) - } - 1 => Err(SysError::IndexOutOfBound), - 2 => Err(SysError::ItemMissing), - 3 => Err(SysError::LengthNotEnough(content.len())), - 4 => Err(SysError::Encoding), - 5 => Err(SysError::SpawnExceededMaxContentLength), - 6 => Err(SysError::SpawnWrongMemoryLimit), - 7 => Err(SysError::SpawnExceededMaxPeakMemory), - r => Err(SysError::Unknown(r)), + let argc = argv.len(); + let mut process_id: u64 = 0; + let mut argv_ptr = alloc::vec![core::ptr::null(); argc + 1]; + for (idx, cstr) in argv.into_iter().enumerate() { + argv_ptr[idx] = cstr.as_ptr(); } + let mut spgs = syscalls::SpawnArgs { + argc: argc as u64, + argv: argv_ptr.as_ptr(), + process_id: &mut process_id as *mut u64, + inherited_fds: inherited_fds.as_ptr(), + }; + syscalls::spawn(index, Source::CellDep, 0, 0, &mut spgs) } diff --git a/src/syscalls/native.rs b/src/syscalls/native.rs index bdaeacd..3a66046 100644 --- a/src/syscalls/native.rs +++ b/src/syscalls/native.rs @@ -537,7 +537,8 @@ pub fn current_cycles() -> u64 { /// by those of the new program. It's cycles consumption consists of two parts: /// /// - Fixed 500 cycles -/// - Initial Loading Cycles () +/// - Initial Loading Cycles () /// /// The arguments used here are: /// @@ -551,17 +552,10 @@ pub fn current_cycles() -> u64 { /// * `place`: A value of 0 or 1: /// + 0: read from cell data /// + 1: read from witness -/// * `bounds`: high 32 bits means `offset`, low 32 bits means `length`. if `length` equals to zero, it read to end instead of reading 0 bytes. -/// * `argc`: argc contains the number of arguments passed to the program +/// * `bounds`: high 32 bits means `offset`, low 32 bits means `length`. if `length` equals to zero, it read to end +/// instead of reading 0 bytes. /// * `argv`: argv is a one-dimensional array of strings -pub fn exec( - index: usize, - source: Source, - place: usize, - bounds: usize, - // argc: i32, - argv: &[&CStr], -) -> u64 { +pub fn exec(index: usize, source: Source, place: usize, bounds: usize, argv: &[&CStr]) -> u64 { // https://www.gnu.org/software/libc/manual/html_node/Program-Arguments.html let argc = argv.len(); let mut argv_ptr = alloc::vec![core::ptr::null(); argc + 1]; @@ -585,79 +579,182 @@ pub fn exec( #[cfg(feature = "ckb2023")] #[repr(C)] pub struct SpawnArgs { - pub memory_limit: u64, - pub exit_code: *mut i8, - pub content: *mut u8, - /// Before calling spawn, content_length should be the length of content; - /// After calling spawn, content_length will be the real size of the returned data. - pub content_length: *mut u64, + /// argc contains the number of arguments passed to the program. + pub argc: u64, + /// argv is a one-dimensional array of strings. + pub argv: *const *const i8, + /// a pointer used to save the process_id of the child process. + pub process_id: *mut u64, + /// an array representing the file descriptors passed to the child process. It must end with zero. + pub inherited_fds: *const u64, } -/// The Spawn and the latter two syscalls: Get Memory Limit and Set Content -/// together, implement a way to call another CKB Script in a CKB Script. +/// The parent process calls the Spawn system call, which creates a new process (a child process) that is an +/// independent ckb-vm instance. It's important to note that the parent process will not be blocked by the child +/// process as a result of this syscall. /// Note: available after ckb2023. /// +/// # Arguments +/// +/// * `index`, `source`, `bounds` and `place` - same as exec. +/// * `spgs` - spawn arguments. +/// /// Returns success or a syscall error. #[cfg(feature = "ckb2023")] -pub fn spawn(index: usize, source: Source, bounds: usize, argv: &[&CStr], spgs: &SpawnArgs) -> u64 { - let argc = argv.len(); - let mut argv_ptr = alloc::vec![core::ptr::null(); argc + 1]; - for (idx, cstr) in argv.into_iter().enumerate() { - argv_ptr[idx] = cstr.as_ptr(); - } - unsafe { +pub fn spawn( + index: usize, + source: Source, + bounds: usize, + place: usize, + spgs: &mut SpawnArgs, +) -> Result<(), SysError> { + let ret = unsafe { syscall( index as u64, source as u64, bounds as u64, - argc as u64, - argv_ptr.as_ptr() as u64, - spgs as *const SpawnArgs as u64, + place as u64, + spgs as *mut SpawnArgs as u64, + 0, 0, SYS_SPAWN, ) + }; + match ret { + 0 => Ok(()), + 1 => Err(SysError::IndexOutOfBound), + 2 => Err(SysError::ItemMissing), + 3 => Err(SysError::Encoding), + 8 => Err(SysError::MaxVmsSpawned), + x => Err(SysError::Unknown(x)), } } -/// Get memory limit. +/// The syscall pauses until the execution of a process specified by pid has ended. /// Note: available after ckb2023. /// -/// Returns a number between 1 and 8, representing 0.5 to 4M of memory. +/// # Arguments +/// +/// * `pid` - process id +/// +/// Returns exit code. #[cfg(feature = "ckb2023")] -pub fn get_memory_limit() -> u64 { - unsafe { syscall(0, 0, 0, 0, 0, 0, 0, SYS_GET_MEMORY_LIMIT) } +pub fn wait(pid: u64) -> Result { + let mut code: u64 = 0; + let ret = unsafe { syscall(pid, &mut code as *mut u64 as u64, 0, 0, 0, 0, 0, SYS_WAIT) }; + match ret { + 0 => Ok(code as i8), + 5 => Err(SysError::WaitFailure), + x => Err(SysError::Unknown(x)), + } } -/// Set content. +/// This syscall is used to get the current process id. Root process ID is 0. /// Note: available after ckb2023. -/// -/// Return the actual written data length or a syscall error. #[cfg(feature = "ckb2023")] -pub fn set_content(buf: &[u8]) -> Result { - let mut len = buf.len() as u64; - let len_ptr: *mut u64 = &mut len; +pub fn process_id() -> u64 { + unsafe { syscall(0, 0, 0, 0, 0, 0, 0, SYS_PROCESS_ID) } +} + +/// This syscall create a pipe with read-write pair of file descriptions. The file descriptor with read permission is +/// located at fds[0], and the corresponding file descriptor with write permission is located at fds[1]. +/// Note: available after ckb2023. +#[cfg(feature = "ckb2023")] +pub fn pipe() -> Result<(u64, u64), SysError> { + let mut fds: [u64; 2] = [0, 0]; + let ret = unsafe { syscall(fds.as_mut_ptr() as u64, 0, 0, 0, 0, 0, 0, SYS_PIPE) }; + match ret { + 0 => Ok((fds[0], fds[1])), + 9 => Err(SysError::MaxFdsCreated), + x => Err(SysError::Unknown(x)), + } +} + +/// This syscall reads data from a pipe via a file descriptor. The syscall Read attempts to read up to value pointed by +/// length bytes from file descriptor fd into the buffer, and the actual length of data read is returned. +/// Note: available after ckb2023. +#[cfg(feature = "ckb2023")] +pub fn read(fd: u64, buffer: &mut [u8]) -> Result { + let mut l: u64 = buffer.len() as u64; + let ret = unsafe { + syscall( + fd, + buffer.as_mut_ptr() as u64, + &mut l as *mut u64 as u64, + 0, + 0, + 0, + 0, + SYS_READ, + ) + }; + match ret { + 0 => Ok(l as usize), + 1 => Err(SysError::IndexOutOfBound), + 6 => Err(SysError::InvalidFd), + 7 => Err(SysError::OtherEndClosed), + x => Err(SysError::Unknown(x)), + } +} + +/// This syscall writes data to a pipe via a file descriptor. The syscall Write writes up to value pointed by length +/// bytes from the buffer, and the actual length of data written is returned. +/// Note: available after ckb2023. +#[cfg(feature = "ckb2023")] +pub fn write(fd: u64, buffer: &[u8]) -> Result { + let mut l: u64 = buffer.len() as u64; + let ret = unsafe { + syscall( + fd, + buffer.as_ptr() as u64, + &mut l as *mut u64 as u64, + 0, + 0, + 0, + 0, + SYS_WRITE, + ) + }; + match ret { + 0 => Ok(l as usize), + 1 => Err(SysError::IndexOutOfBound), + 6 => Err(SysError::InvalidFd), + 7 => Err(SysError::OtherEndClosed), + x => Err(SysError::Unknown(x)), + } +} + +/// This syscall retrieves the file descriptors available to the current process, which are passed in from the parent +/// process. These results are copied from the inherited_fds parameter of the Spawn syscall. +/// Note: available after ckb2023. +#[cfg(feature = "ckb2023")] +pub fn inherited_file_descriptors(fds: &mut [u64]) { + let mut l: u64 = fds.len() as u64; unsafe { syscall( - buf.as_ptr() as u64, - len_ptr as u64, + fds.as_mut_ptr() as u64, + &mut l as *mut u64 as u64, 0, 0, 0, 0, 0, - SYS_SET_CONTENT, + SYS_INHERITED_FD, ) }; - Ok(len) } -/// Get current memory. +/// This syscall manually closes a file descriptor. After calling this, any attempt to read/write the file descriptor +/// pointed to the other end would fail. /// Note: available after ckb2023. -/// -/// Returns the sum of the memory of all living vm instances. #[cfg(feature = "ckb2023")] -pub fn current_memory() -> u64 { - unsafe { syscall(0, 0, 0, 0, 0, 0, 0, SYS_CURRENT_MEMORY) } +pub fn close(fd: u64) -> Result<(), SysError> { + let ret = unsafe { syscall(fd, 0, 0, 0, 0, 0, 0, SYS_CLOSE) }; + match ret { + 0 => Ok(()), + 6 => Err(SysError::InvalidFd), + x => Err(SysError::Unknown(x)), + } } /// Load extension field associated either with an input cell, a dep cell, or From 7f8f8c265b58ee0b291ab2924e861b1a530f4ef4 Mon Sep 17 00:00:00 2001 From: mohanson Date: Wed, 24 Apr 2024 17:31:16 +0800 Subject: [PATCH 2/2] Fix make test --- .../spawn-caller-by-code-hash/src/entry.rs | 39 +++++++++++-------- .../spawn-caller-by-code-hash/src/error.rs | 16 +++++--- src/high_level.rs | 10 ++--- src/syscalls/native.rs | 4 +- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/contracts/spawn-caller-by-code-hash/src/entry.rs b/contracts/spawn-caller-by-code-hash/src/entry.rs index bd4ae12..fc2ecda 100644 --- a/contracts/spawn-caller-by-code-hash/src/entry.rs +++ b/contracts/spawn-caller-by-code-hash/src/entry.rs @@ -1,29 +1,34 @@ // Import from `core` instead of from `std` since we are in no-std mode use crate::error::Error; -use alloc::vec; +use ckb_std::ckb_constants::Source; use ckb_std::ckb_types::core::ScriptHashType; use ckb_std::high_level::{load_script, spawn_cell}; +use ckb_std::syscalls; use core::ffi::CStr; use core::result::Result; pub fn main() -> Result<(), Error> { - let arg1 = CStr::from_bytes_with_nul(b"hello\0").unwrap(); - let arg2 = CStr::from_bytes_with_nul(b"world\0").unwrap(); + let argv = [ + CStr::from_bytes_with_nul(b"hello\0").unwrap(), + CStr::from_bytes_with_nul(b"world\0").unwrap(), + ]; + let mut std_fds: [u64; 2] = [0, 0]; + let mut son_fds: [u64; 3] = [0, 0, 0]; + let (r0, w0) = syscalls::pipe()?; + std_fds[0] = r0; + son_fds[1] = w0; + let (r1, w1) = syscalls::pipe()?; + std_fds[1] = w1; + son_fds[0] = r1; let code_hash = load_script().unwrap().args().raw_data(); - ckb_std::debug!("code_hash: {:?}", code_hash); - - let mut content = vec![0; 80]; - let ret = spawn_cell( - &code_hash[..], - ScriptHashType::Data1, - &[arg1, arg2][..], - 8, - &mut content, + spawn_cell(&code_hash[..], ScriptHashType::Data1, &argv, &son_fds)?; + let mut buf: [u8; 256] = [0; 256]; + let len = syscalls::read(std_fds[0], &mut buf)?; + assert_eq!(len, 10); + buf[len] = 0; + assert_eq!( + CStr::from_bytes_until_nul(&buf).unwrap().to_str().unwrap(), + "helloworld" ); - assert!(ret == Ok(0)); - assert!(content.len() == 10); - content.resize(content.len() + 1, 0); - let c_str = CStr::from_bytes_until_nul(&content).unwrap(); - assert_eq!(c_str.to_str().unwrap(), "helloworld"); Ok(()) } diff --git a/contracts/spawn-caller-by-code-hash/src/error.rs b/contracts/spawn-caller-by-code-hash/src/error.rs index ce0bdeb..b78e033 100644 --- a/contracts/spawn-caller-by-code-hash/src/error.rs +++ b/contracts/spawn-caller-by-code-hash/src/error.rs @@ -7,9 +7,11 @@ pub enum Error { ItemMissing, LengthNotEnough, Encoding, - SpawnExceededMaxContentLength, - SpawnWrongMemoryLimit, - SpawnExceededMaxPeakMemory, + WaitFailure, + InvalidFd, + OtherEndClosed, + MaxVmsSpawned, + MaxFdsCreated, } impl From for Error { @@ -20,9 +22,11 @@ impl From for Error { ItemMissing => Self::ItemMissing, LengthNotEnough(_) => Self::LengthNotEnough, Encoding => Self::Encoding, - SpawnExceededMaxContentLength => Self::SpawnExceededMaxContentLength, - SpawnWrongMemoryLimit => Self::SpawnWrongMemoryLimit, - SpawnExceededMaxPeakMemory => Self::SpawnExceededMaxPeakMemory, + WaitFailure => Self::WaitFailure, + InvalidFd => Self::InvalidFd, + OtherEndClosed => Self::OtherEndClosed, + MaxVmsSpawned => Self::MaxVmsSpawned, + MaxFdsCreated => Self::MaxFdsCreated, Unknown(err_code) => panic!("unexpected sys error {}", err_code), } } diff --git a/src/high_level.rs b/src/high_level.rs index 475413d..f689ddd 100644 --- a/src/high_level.rs +++ b/src/high_level.rs @@ -680,17 +680,14 @@ pub fn exec_cell( /// - CString::new("arg0").unwrap().as_c_str(); /// - if you want to pass a piece of bytes data, you may encode it to hexadecimal string or other format: /// - high_level::encode_hex(&vec![0xff, 0xfe, 0xfd]); -/// * `memory_limit` - a number between 1 and 8. -/// - note each tick represents an additional 0.5M of memory. -/// * `content` - a buffer to saving the output by sub script. -/// - note the size of content will be shrinked after call. +/// * `inherited_fds` - the fd list to be passed to the child process. #[cfg(feature = "ckb2023")] pub fn spawn_cell( code_hash: &[u8], hash_type: ScriptHashType, argv: &[&CStr], inherited_fds: &[u64], -) -> Result<(), SysError> { +) -> Result { let index = look_for_dep_with_hash2(code_hash, hash_type)?; let argc = argv.len(); let mut process_id: u64 = 0; @@ -704,5 +701,6 @@ pub fn spawn_cell( process_id: &mut process_id as *mut u64, inherited_fds: inherited_fds.as_ptr(), }; - syscalls::spawn(index, Source::CellDep, 0, 0, &mut spgs) + syscalls::spawn(index, Source::CellDep, 0, 0, &mut spgs)?; + Ok(process_id) } diff --git a/src/syscalls/native.rs b/src/syscalls/native.rs index 3a66046..67943d7 100644 --- a/src/syscalls/native.rs +++ b/src/syscalls/native.rs @@ -607,7 +607,7 @@ pub fn spawn( bounds: usize, place: usize, spgs: &mut SpawnArgs, -) -> Result<(), SysError> { +) -> Result { let ret = unsafe { syscall( index as u64, @@ -621,7 +621,7 @@ pub fn spawn( ) }; match ret { - 0 => Ok(()), + 0 => Ok(unsafe { *spgs.process_id }), 1 => Err(SysError::IndexOutOfBound), 2 => Err(SysError::ItemMissing), 3 => Err(SysError::Encoding),