-
Notifications
You must be signed in to change notification settings - Fork 0
Home
The timeout-group project is an open-source fork of the standard coreutils package supplied on Linux. The project is stripped to the bare minimum of installing just one program called timeoutg. This program is a modified version of the standard timeout (1).
It was observed that under some circumstances the order of process termination in a group created by timeout (1) is not deterministic. Specifically, if timeout is used to run a bash function or script that itself may create child processes, and all this process tree has to be killed by a signal, some of the child processes may exit later than the main bash process running the function or script. This behaviour appeared in bash versions >= 4.3. It was absent in bash 4.2.53, the latest in 4.2 series. This bug or feature creates multiple potential problems when the logical sequence of events during termination becomes undefined.
The extension of timeout solves the problem by waiting internally for all member of the process group to exit, not only for the process immediately launched by timeout, which is bash in the example above. See the in-line help, timeoutg --help, for details of usage.
The project is kept in a separate public repository due to the GPL licence of coreutil.
The modified timeoutg uses functions from the procps (also called procps-ng) library to parse the process tree until there is only one remaining member of a given group: the timeoutg process itself. The new behaviour has to be explicitly requested by the user using the –wait-for-process-group option. The option takes one argument: the wait duration. If some process are still found after this time interval, they are forcefully killed by SIGKILL (similar to the original -k option of timeout).
Notice that although timeout-group project builds a single executable to be installed, it compiles all the source files of the former coreutils into object files. Thus, the same build dependencies shall be satisfied as for coreutils. Untangling the build process further complicates the build system considerably and increases the chance of conflicts with upstream coreutils integration. Extraneous build dependencies appear the lesser of the two evils. There are no corresponding installation and run-time dependencies because the produced object files are linked statically.
Users shall commonly install the timeoutg utility from the pre-build RPM package. The information below is necessary only for developers updating timeout-group or porting it to new platforms.
The timeout-group package is a fork of the original coreutils package developed at Savannah. However, Linux variants, such as Debian/Ubuntu and RedHat/Fedore distribute their own, customized versions of coreutils that have multiple and sufficiently subtle differences. Therefore, there are two options to build timeout-group: (1) directly from the source, and (2) as a distribution-specific package.
The master (tip) version of timeout-group follows the master version of coreutils. It requires the latest versions of many GNU utilities (such as autotools and gettext) that are not available in older Linux distributions. It is suggested to install the timeout-group version that is closest (or matches) the coreutils version of your Linux. For example, if your system uses 8.22 family of coreutils, use timeout-group-v8.22 branch as follows:
$ git checkout timeout-group-v8.22
In the pristine source tree, run the provided bootstrap script. It will download the dependencies of coreutils to your working tree and run the needed autotools commands. Then run ./configure script with desired options, make and make install.
Most distributions provide software in the form of packages. This section describes how to build an RPM package for timeout-group. See also [Updating to New Platforms] (#updating-to-new-platforms).
Specific Linux versions provide coreutils that are somewhat modified with respect to the baseline of the same version. Modifications are two-fold. First, many additional source and header files are included, roughly corresponding to the source dependencies downloaded when running the bootstrap script. The autotools-generated files such as configure and Makefile.am are also pre-included. Second, distributions add custom patches, commonly, bug fixes backported from newer versions of coreutils. As an example, at the moment of writing the RHEL 7.2 version of coreutils includes 27 patches with respect to the pristine version. Most of these patches are likely irrelevant for timeout (1), but tracing all possible modifications is not practical. Therefore, it is recommended to build custom packages on top of the latest releases of coreutils for the given platform.
Check the version of coreutils on your box and checkout the timeout-group branch corresponding to your version. If such a branch does not exist yet, create it following the instructions in [Updating to New Platforms] (#updating-to-new-platforms). Then follow the instructions for building your package that are provided within the branch source tree in packagers/rpm/rpm.howto file.
Maintenance covers several activities: following coreutils development, updating timeout-group to new platforms, and further extending timeout-group.
Checkout timeout-group (master branch).
Add the original coreutils repository as a new remote, then pull from it, and push back to timeout-group:
$ git remote add upstream http://git.savannah.gnu.org/r/coreutils.git
$ git pull upstream master
$ git push
As explained in [Building timeout-group] (#building-timeout-group), it is recommended to make timeout-group as close as possible to the version of coreutils natively provided by the platform. As an example, RHEL 7.2 uses coreutils-8.22-15.el7_2.1 at the moment of writing. Therefore, it is recommended to create and install a custom version of timeout-group based on version 8.22 of coreutils. This custom version will be most adapted to the platform. As a general rule, one should use the nominal version of coreutils for your platform, i.e., version 8.22 for RHEL 7.2, version 8.25 for Ubuntu 16.04 LTS, and so on, as the base for your timeout-group installation.
The original development of timeout-group was based on releases 8.21 and 8.22. Before writing this example, there was no custom version based on 8.25 release of coreutils, which is the version in Ubuntu 16.04 LTS. The example below shows how to port the timeout-group code to version 8.25.
$ git show-ref --tags | grep v8.25
7e4c8b18b232b69887a1a8f088af88a9596274bc refs/tags/v8.25
$ git log -1 7e4c8b18b232b69887a1a8f088af88a9596274bc
commit 68f73f23866d6137e9c8d88d86073b33588d7b56
Author: Pádraig Brady <P@draigBrady.com>
Date: Wed Jan 20 10:31:56 2016 +0000
version 8.25
* NEWS: Record release date.
Therefore, version 8.25 of timeout-group shall be forked from commit 68f73f23866d6137e9c8d88d86073b33588d7b56 of coreutils.
To update timeout-group customizations to version 8.25, it is best to start with a closest version. At the moment of writing, the custom timeout is available for versions 8.21 and 8.22:
$ git branch --all
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/timeout-group-v8.21
remotes/origin/timeout-group-v8.22
...
Therefore, we choose the 8.22 variant as the base. If a closer version were available, e.g., 8.26, it could provide a better starting point. Note: please use a standard naming convention for your branches to simplify this search.
Find all the modifications applied on timeout-group-v8.22 branch (output trimmed):
$ git log master..remotes/origin/timeout-group-v8.22 --oneline
7c806c5 Write up instructions for generating RPMs from the source tree.
... lots of commits skipped...
7959bf3 First mostly working implementation...
$ git log --pretty=%p -n 1 7959bf3
3384461
The second git log command shows the parent of the first commit 7959bf3 on the timeout-group-v8.22 branch. We need to re-apply all differences from 3384461 and up to and including 7c806c5 to the commit tagged as version 8.25.
Given the start of version 8.25 and the range of changes to apply, the new version is created as:
$ git rebase --onto 68f73f23866d6137e9c8d88d86073b33588d7b56 3384461 7c806c5
Likely, some of the commits cannot be re-applied cleanly. In such cases, the git rebase command will interrupt and return to the shell prompt with a message like:
...skipped...
Auto-merging src/timeout.c
CONFLICT (content): Merge conflict in src/timeout.c
Failed to merge in the changes.
Patch failed at 0007 Minor, add myself to the list of authors / people who modified the timeout.
The copy of the patch that failed is found in:
/home/dmitrym/projects/acfr/timeout/master/timeout-group/.git/rebase-apply/patch
When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Edit manually the conflicting file src/timeout.c to resolve the merge conflict; even if the merge conflict affects just a few lines, the merge may be non-trivial. Then run:
$ git add src/timeout.c
$ git rebase --continue
More conflicts may occur in later commits, resolve all as needed. Finally, when all the commits have been re-applied on top of the fork base, the source tree will be in the detached head state. To preserve your work, create a new local branch:
$ git checkout -b timeout-group-v8.25
Please follow the suggested convention for branch names. Now all the version 8.22 changes have been re-applied to version 8.25. Because of the differences between the two versions of coreutils, some other modifications may be needed. Try to build your version as described in [Building from Source] (#building-from-source) and make further changes if the build fails. Install and see if timeoutg works by running, e.g., 'timeoutg 2 sleep 10' and observing that it terminates in 2 seconds. Then create a new remote branch based on the local and set that remote branch as an upstream to the local:
$ git push -u origin timeout-group-v8.25
When switching branches, make sure to run the following command after the checkout:
$ git submodule update --init
Otherwise, some of the submodules may be initialized according to the requirements of the previously checked-out branch of coreutils, and therefore, a different version of a submodule may cause errors during the build- or run-time. It is not expected for timeout-group to customize any submodule locations with respect to coreutils requirements.
In the future, more features could be requested from timeoutg utility. Some could be as simple as better usage help. Checkout the branch of interest and add your extensions.
Consider if your additions are sufficiently general to be applicable to other branches. If so, use git rebase --onto or git cherry-pick to transfer your changes between the branches.