@@ -483,6 +483,7 @@ impl ActiveProcess {
483483 next_mapped_host_fd: MAPPED_HOST_FD_START,
484484 pending_execution_events: VecDeque::new(),
485485 pending_self_signal_exit: None,
486+ pending_wasm_signals: VecDeque::new(),
486487 child_processes: BTreeMap::new(),
487488 next_child_process_id: 0,
488489 http_servers: BTreeMap::new(),
@@ -4523,6 +4524,8 @@ where
45234524 let (connection_id, session_id, vm_id) = self.vm_scope_for(&request.ownership)?;
45244525 self.require_owned_vm(&connection_id, &session_id, &vm_id)?;
45254526
4527+ self.drain_root_signal_state_events(&vm_id, &payload.process_id)?;
4528+
45264529 let handlers = self
45274530 .vms
45284531 .get(&vm_id)
@@ -4536,6 +4539,77 @@ where
45364539 })
45374540 }
45384541
4542+ fn drain_root_signal_state_events(
4543+ &mut self,
4544+ vm_id: &str,
4545+ process_id: &str,
4546+ ) -> Result<(), SidecarError> {
4547+ let mut deferred = VecDeque::new();
4548+
4549+ loop {
4550+ let event = {
4551+ let Some(vm) = self.vms.get_mut(vm_id) else {
4552+ break;
4553+ };
4554+ let Some(process) = vm.active_processes.get_mut(process_id) else {
4555+ break;
4556+ };
4557+ if let Some(event) = process.pending_execution_events.pop_front() {
4558+ Some(event)
4559+ } else {
4560+ match process.execution.poll_event_blocking(Duration::ZERO) {
4561+ Ok(event) => event,
4562+ Err(SidecarError::Execution(message))
4563+ if (process.runtime == GuestRuntimeKind::JavaScript
4564+ && closed_javascript_event_channel(&message))
4565+ || (process.runtime == GuestRuntimeKind::Python
4566+ && closed_python_event_channel(&message))
4567+ || (process.runtime == GuestRuntimeKind::WebAssembly
4568+ && closed_wasm_event_channel(&message)) =>
4569+ {
4570+ None
4571+ }
4572+ Err(error) => return Err(error),
4573+ }
4574+ }
4575+ };
4576+
4577+ let Some(event) = event else {
4578+ break;
4579+ };
4580+
4581+ match event {
4582+ ActiveExecutionEvent::SignalState {
4583+ signal,
4584+ registration,
4585+ } => {
4586+ if let Some(vm) = self.vms.get_mut(vm_id) {
4587+ apply_process_signal_state_update(
4588+ &mut vm.signal_states,
4589+ process_id,
4590+ signal,
4591+ registration,
4592+ );
4593+ }
4594+ }
4595+ other => deferred.push_back(other),
4596+ }
4597+ }
4598+
4599+ if let Some(vm) = self.vms.get_mut(vm_id) {
4600+ if let Some(process) = vm.active_processes.get_mut(process_id) {
4601+ for event in deferred.into_iter().rev() {
4602+ if process.pending_execution_events.len() >= MAX_PROCESS_EVENT_QUEUE {
4603+ return Err(process_event_queue_overflow_error());
4604+ }
4605+ process.pending_execution_events.push_front(event);
4606+ }
4607+ }
4608+ }
4609+
4610+ Ok(())
4611+ }
4612+
45394613 pub(crate) async fn get_zombie_timer_count(
45404614 &mut self,
45414615 request: &RequestFrame,
@@ -4627,7 +4701,7 @@ where
46274701 KillBehavior::SharedV8DispatchOrTerminate
46284702 }
46294703 ActiveExecution::Wasm(execution) if execution.uses_shared_v8_runtime() => {
4630- KillBehavior::SharedV8Terminate
4704+ KillBehavior::SharedV8DispatchOrTerminate
46314705 }
46324706 ActiveExecution::Python(execution) if execution.uses_shared_v8_runtime() => {
46334707 KillBehavior::SharedV8Terminate
@@ -4680,8 +4754,37 @@ where
46804754 }
46814755 }
46824756 KillBehavior::SharedV8DispatchOrTerminate => {
4683- if signal != 0 && !dispatch_v8_process_signal(process, signal)? {
4684- process.execution.terminate()?;
4757+ if signal != 0 {
4758+ let is_shared_wasm = matches!(
4759+ &process.execution,
4760+ ActiveExecution::Wasm(execution) if execution.uses_shared_v8_runtime()
4761+ );
4762+ if is_shared_wasm {
4763+ let action = vm
4764+ .signal_states
4765+ .get(process_id)
4766+ .and_then(|handlers| handlers.get(&(signal as u32)))
4767+ .map(|registration| ®istration.action);
4768+ match action {
4769+ Some(SignalDispositionAction::Ignore) => {}
4770+ Some(SignalDispositionAction::User) => {
4771+ process.pending_wasm_signals.push_back(signal);
4772+ }
4773+ Some(SignalDispositionAction::Default) | None => {
4774+ if !matches!(
4775+ canonical_signal_name(signal),
4776+ Some("SIGWINCH" | "SIGCHLD" | "SIGURG")
4777+ ) {
4778+ process.execution.terminate()?;
4779+ process.queue_pending_execution_event(
4780+ ActiveExecutionEvent::Exited(128 + signal),
4781+ )?;
4782+ }
4783+ }
4784+ }
4785+ } else if !dispatch_v8_process_signal(process, signal)? {
4786+ process.execution.terminate()?;
4787+ }
46854788 }
46864789 }
46874790 KillBehavior::Noop => {}
@@ -8747,9 +8850,10 @@ where
87478850 "ESRCH: unknown process pid {target_pid}"
87488851 )));
87498852 };
8750- if let Some(session) = target.execution.javascript_v8_session_handle().filter(
8751- |_| matches!(&target.execution, ActiveExecution::Javascript(execution) if execution.uses_shared_v8_runtime())
8752- || matches!(&target.execution, ActiveExecution::Wasm(execution) if execution.uses_shared_v8_runtime()),
8853+ if matches!(&target.execution, ActiveExecution::Wasm(execution) if execution.uses_shared_v8_runtime()) {
8854+ target.pending_wasm_signals.push_back(signal);
8855+ } else if let Some(session) = target.execution.javascript_v8_session_handle().filter(
8856+ |_| matches!(&target.execution, ActiveExecution::Javascript(execution) if execution.uses_shared_v8_runtime()),
87538857 ) {
87548858 dispatch_v8_session_signal_async(session, signal);
87558859 } else if !dispatch_v8_process_signal(target, signal)? {
@@ -16754,6 +16858,10 @@ where
1675416858 "action": "default",
1675516859 }))
1675616860 }
16861+ "process.take_signal" => {
16862+ let signal = process.pending_wasm_signals.pop_front();
16863+ Ok(signal.map(Value::from).unwrap_or(Value::Null).into())
16864+ }
1675716865 "process.umask" => {
1675816866 let new_mask = javascript_sync_rpc_arg_u32_optional(&request.args, 0, "process umask")?;
1675916867 kernel
@@ -24141,6 +24249,13 @@ fn dispatch_v8_process_signal(process: &ActiveProcess, signal: i32) -> Result<bo
2414124249 let Some(signal_name) = signal_name_for_stream_event(signal) else {
2414224250 return Ok(false);
2414324251 };
24252+ if matches!(&process.execution, ActiveExecution::Wasm(execution) if execution.uses_shared_v8_runtime())
24253+ {
24254+ if let Some(session) = process.execution.javascript_v8_session_handle() {
24255+ dispatch_v8_session_signal_async(session, signal);
24256+ return Ok(true);
24257+ }
24258+ }
2414424259 process.execution.send_javascript_stream_event(
2414524260 "signal",
2414624261 json!({
0 commit comments