The GNU coreutils timeout command encapsulates a lot of these issues. It's surprisingly difficult to handle all the edge cases and races.
https://www.maizure.org/projects/decoded-gnu-coreutils/timeo...
https://www.maizure.org/projects/decoded-gnu-coreutils/timeo...
https://github.com/MaiZure/coreutils-8.3/issues/1#issuecomme...