@@ -179,6 +179,107 @@ pub trait CommandExt: Sealed {
179179 /// ```
180180 #[ stable( feature = "process_set_process_group" , since = "1.64.0" ) ]
181181 fn process_group ( & mut self , pgroup : i32 ) -> & mut process:: Command ;
182+
183+ /// Blocks the given signal for the child process at the time it is started.
184+ ///
185+ /// The set of blocked signals for a process is known as its signal mask.
186+ /// Use this method to block some signals.
187+ ///
188+ /// This method corresponds to calling [`sigaddset`] with the given signal.
189+ ///
190+ /// # Notes
191+ ///
192+ /// Rust's current default is to not block any signals in child processes. This may change in
193+ /// the future to inheriting the current process's signal mask.
194+ ///
195+ /// This method is idempotent: blocking a signal that's already blocked results in
196+ /// success and has no effect.
197+ ///
198+ /// Blocking some signals like `SIGSEGV` can lead to undefined behavior in
199+ /// the child. See the [`pthread_sigmask`] man page for more information.
200+ ///
201+ /// # Errors
202+ ///
203+ /// Returns an `InvalidInput` error if the signal is invalid.
204+ ///
205+ /// # Examples
206+ ///
207+ /// Start a process with `SIGINT` blocked:
208+ ///
209+ /// ```no_run
210+ /// #![feature(process_sigmask)]
211+ /// #
212+ /// use std::process::Command;
213+ /// use std::os::unix::process::CommandExt;
214+ ///
215+ /// Command::new("sleep")
216+ /// .arg("10")
217+ /// // On most platforms, SIGINT is signal 2.
218+ /// .block_signal(2)?
219+ /// .spawn()?;
220+ /// #
221+ /// # Ok::<_, Box<dyn std::error::Error>>(())
222+ /// ```
223+ ///
224+ /// [`sigaddset`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigaddset.html
225+ /// [`pthread_sigmask`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html
226+ #[ unstable( feature = "process_sigmask" , issue = "none" ) ]
227+ fn block_signal ( & mut self , signal : i32 ) -> io:: Result < & mut process:: Command > ;
228+
229+ /// Unblocks the given signal for the child process at the time it is started.
230+ ///
231+ /// The set of blocked signals for a process is known as its signal mask.
232+ /// Use this method to unblock a signal.
233+ ///
234+ /// This method corresponds to calling [`sigdelset`] with the given signal.
235+ ///
236+ /// # Notes
237+ ///
238+ /// Rust's current default is to not block any signals in child processes. This may change in
239+ /// the future to inheriting the current process's signal mask.
240+ ///
241+ /// This method is idempotent: unblocking a signal that's already unblocked results in
242+ /// success and has no effect.
243+ ///
244+ /// # Errors
245+ ///
246+ /// Returns an `InvalidInput` error if the signal is invalid.
247+ ///
248+ /// # Examples
249+ ///
250+ /// Start a process with `SIGHUP` unblocked:
251+ ///
252+ /// ```no_run
253+ /// #![feature(process_sigmask)]
254+ /// #
255+ /// use std::process::Command;
256+ /// use std::os::unix::process::CommandExt;
257+ ///
258+ /// Command::new("sleep")
259+ /// .arg("10")
260+ /// // On most platforms, SIGHUP is signal 1.
261+ /// .unblock_signal(1)?
262+ /// .spawn()?;
263+ /// #
264+ /// # Ok::<_, Box<dyn std::error::Error>>(())
265+ /// ```
266+ ///
267+ /// [`sigdelset`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigdelset.html
268+ /// [`pthread_sigmask`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html
269+ #[ unstable( feature = "process_sigmask" , issue = "none" ) ]
270+ fn unblock_signal ( & mut self , signal : i32 ) -> io:: Result < & mut process:: Command > ;
271+
272+ /// Returns true if a signal will be blocked in the child process at the time it is started.
273+ ///
274+ /// This method corresponds to calling [`sigismember`] with the given signal.
275+ ///
276+ /// # Errors
277+ ///
278+ /// Returns an `InvalidInput` error if the signal is invalid.
279+ ///
280+ /// [`sigismember`]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sigismember.html
281+ #[ unstable( feature = "process_sigmask" , issue = "none" ) ]
282+ fn will_block_signal ( & self , signal : i32 ) -> io:: Result < bool > ;
182283}
183284
184285#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -224,6 +325,20 @@ impl CommandExt for process::Command {
224325 self . as_inner_mut ( ) . pgroup ( pgroup) ;
225326 self
226327 }
328+
329+ fn block_signal ( & mut self , signal : i32 ) -> io:: Result < & mut process:: Command > {
330+ self . as_inner_mut ( ) . signal_mask ( ) ?. insert ( signal) ?;
331+ Ok ( self )
332+ }
333+
334+ fn unblock_signal ( & mut self , signal : i32 ) -> io:: Result < & mut process:: Command > {
335+ self . as_inner_mut ( ) . signal_mask ( ) ?. remove ( signal) ?;
336+ Ok ( self )
337+ }
338+
339+ fn will_block_signal ( & self , signal : i32 ) -> io:: Result < bool > {
340+ self . as_inner ( ) . get_signal_mask ( ) ?. contains ( signal)
341+ }
227342}
228343
229344/// Unix-specific extensions to [`process::ExitStatus`] and
0 commit comments