Git commit e5a9295bccf07ed0ca9d9729b7ca72ec193f5a2d by Michael Pyne. Committed on 14/07/2022 at 04:11. Pushed by mpyne into branch 'master'.
Support SIGHUP for graceful script exit. This helps if a user started a long build without --stop-on-failure and needs it to stop without risking interrupting kdesrc-build during an install step. Fixes #96. M +97 -1 doc/index.docbook M +10 -1 doc/man-kdesrc-build.1.docbook M +59 -2 modules/ksb/TaskManager.pm https://invent.kde.org/sdk/kdesrc-build/commit/e5a9295bccf07ed0ca9d9729b7ca72ec193f5a2d diff --git a/doc/index.docbook b/doc/index.docbook index 894fc38..f086c8c 100644 --- a/doc/index.docbook +++ b/doc/index.docbook @@ -2,7 +2,7 @@ <!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.5-Based Variant V1.1//EN" "dtd/kdedbx45.dtd" [ <!-- Documentation for kdesrc-build. - Copyright (c) 2005-2008, 2010-2020 Michael Pyne <mp...@kde.org> + Copyright (c) 2005-2008, 2010-2022 Michael Pyne <mp...@kde.org> Copyright (c) 2005 Carlos Leonhard Woelz <carloswo...@imap-mail.com> Copyright (c) 2009 Burkhard Lück <lu...@hube-lueck.de> @@ -4326,6 +4326,102 @@ as well. </sect2> +<sect2 id="stopping-the-build-early"> +<title>Stopping the build early</title> + +<sect3 id="the-build-continues"> +<title>The build normally continues even if failures occur</title> + +<para>&kdesrc-build; normally will update, build and install all modules +in the specified list of modules to build, even if a module fails to build. +This is usually a convenience to allow you to update software packages even +if a simple mistake is made in one of the source repositories during +development that causes the build to break. +</para> + +<para> +However you may wish for &kdesrc-build; to stop what it is doing once a +module fails to build and install. This can help save you time that will be +wasted trying to make progress when modules remaining in the build list will +not be able to successfully build either, especially if you have not ever +successfully built the modules in the list. +</para> + +</sect3> + +<sect3 id="stop-on-failure-stops-early"> +<title>Stopping early with --stop-on-failure</title> + +<para> +The primary method to do this is to use the +<link linkend="cmdline-stop-on-failure">--stop-on-failure</link> +command line option when you run &kdesrc-build;. +</para> + +<para>This option can also be set in the +<link linkend="conf-stop-on-failure">configuration file</link> to make +it the normal mode of operation. +</para> + +<para>It is also possible to tell &kdesrc-build; at runtime to stop building +<emphasis>after</emphasis> completing the current module it is working on. +This is as opposed to interrupting &kdesrc-build; using a command like +<keycombo action="simul">&Ctrl;<keycap>C</keycap></keycombo>, which interrupts +&kdesrc-build; immediately, losing the progress of the current module. +</para> + +<important><para>Interrupting &kdesrc-build; during a module install when +the <link linkend="conf-use-clean-install">use-clean-install</link> option +is enabled will mean that the interrupted module will be unavailable until +&kdesrc-build; is able to successfully build the module!</para> + +<para>If you need to interrupt &kdesrc-build; without permitting a graceful shutdown +in this situation, at least try to avoid doing this while &kdesrc-build; is +installing a module.</para> +</important> + +</sect3> + +<sect3 id="stopping-early-without-stop-on-failure"> +<title>Stopping &kdesrc-build; early without --stop-on-failure</title> + +<para>As mentioned above, it is possible to cause &kdesrc-build; to gracefully +shutdown early once it has completed the module it is currently working on. +To do this, you need to send the POSIX <literal>HUP</literal> signal to &kdesrc-build; +</para> + +<para>You can do this with a command such as <command>pkill</command> (on &Linux; systems) as follows:</para> + +<programlisting> +<prompt>$ </prompt><userinput><command>pkill <option>-HUP</option> kdesrc-build</command></userinput> +</programlisting> + +<para>If done successfully, you will see a message in the &kdesrc-build; output similar +to:</para> + +<programlisting> +[ build ] recv SIGHUP, will end after this module +</programlisting> + +<note> +<para>&kdesrc-build; may show this message multiple times depending on the +number of individual &kdesrc-build; processes that are active. This is +normal and not an indication of an error.</para> +</note> + +<para> +Once &kdesrc-build; has acknowledged the signal, it will stop processing +after the current module is built and installed. If &kdesrc-build; is still +updating source code when the request is received, &kdesrc-build; will stop +after the module source code update is complete. Once both the update and build +processes have stopped early, &kdesrc-build; will print its partial results +and exit. +</para> + +</sect3> + +</sect2> + <sect2 id="building-successfully"> <title>How &kdesrc-build; tries to ensure a successful build</title> diff --git a/doc/man-kdesrc-build.1.docbook b/doc/man-kdesrc-build.1.docbook index 82f5786..098755d 100644 --- a/doc/man-kdesrc-build.1.docbook +++ b/doc/man-kdesrc-build.1.docbook @@ -6,7 +6,7 @@ <!-- Man page for kdesrc-build. - Copyright (c) 2011, 2014-2020 Michael Pyne <mp...@kde.org> + Copyright (c) 2011, 2014-2020, 2022 Michael Pyne <mp...@kde.org> Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later @@ -1157,6 +1157,15 @@ others </variablelist> </refsect1> +<refsect1> +<title>SIGNALS</title> + +<para>&kdesrc-build; supports <literal>SIGHUP</literal>, which if received +will cause &kdesrc-build; to exit after the current modules for the +build thread (and update thread, if still active) have completed.</para> + +</refsect1> + <refsect1> <title>FILES</title> diff --git a/modules/ksb/TaskManager.pm b/modules/ksb/TaskManager.pm index 976147c..6194275 100644 --- a/modules/ksb/TaskManager.pm +++ b/modules/ksb/TaskManager.pm @@ -34,6 +34,8 @@ use Mojo::URL; use IO::Select; use POSIX qw(EINTR WNOHANG); +my $DO_STOP = 0; + sub new ($class, $app) { assert_isa($app, 'ksb::Application'); @@ -72,6 +74,13 @@ sub runAllTasks ($self) } else { whisper ("Using no IPC mechanism\n"); + # If the user sends SIGHUP during the build, we should allow the + # current module to complete and then exit early. + local $SIG{HUP} = sub { + say "[noasync] recv SIGHUP, will end after this module"; + $DO_STOP = 1; + }; + note ("\n b[<<< Update Process >>>]\n"); $result = _handle_updates ($ipc, $ctx); @@ -131,6 +140,11 @@ sub _handle_updates ($ipc, $ctx) my $hadError = 0; foreach my $module (@update_list) { + if ($DO_STOP) { + note (" y[b[* * *] Early exit requested, aborting updates."); + last; + } + $ipc->setLoggedModule($module->name()); # Note that this must be in this order to avoid accidentally not @@ -251,6 +265,11 @@ EOF $statusViewer->numberModulesTotal($num_modules); while (my $module = shift @modules) { + if ($DO_STOP) { + note (" y[b[* * *] Early exit requested, aborting updates."); + last; + } + my $moduleName = $module->name(); my $moduleSet = $module->moduleSet()->name(); my $modOutput = $moduleName; @@ -378,20 +397,40 @@ sub _handle_async_build ($ipc, $ctx) my $result = 0; my $monitorPid = fork; + my $updaterPid; if ($monitorPid == 0) { # child my $updaterToMonitorIPC = ksb::IPC::Pipe->new(); - my $updaterPid = fork; + $updaterPid = fork; $SIG{INT} = sub { POSIX::_exit(EINTR); }; if ($updaterPid) { + # If the user sends SIGHUP during the build, we should allow the + # current module to complete and then exit early. + local $SIG{HUP} = sub { + say "[updater] recv SIGHUP, will end after this module"; + + $DO_STOP = 1; + }; + $0 = 'kdesrc-build-updater'; $updaterToMonitorIPC->setSender(); ksb::Debug::setIPC($updaterToMonitorIPC); POSIX::_exit (_handle_updates ($updaterToMonitorIPC, $ctx)); } else { + # If the user sends SIGHUP during the build, we should allow the + # current module to complete and then exit early. + local $SIG{HUP} = sub { + say "[monitor] recv SIGHUP, will end after this module"; + + # If we haven't recv'd yet, forward to monitor in case user didn't + # send to process group + kill 'HUP', $updaterPid unless $DO_STOP; + $DO_STOP = 1; + }; + $0 = 'kdesrc-build-monitor'; $ipc->setSender(); $updaterToMonitorIPC->setReceiver(); @@ -399,10 +438,28 @@ sub _handle_async_build ($ipc, $ctx) $ipc->setLoggedModule('#monitor#'); # This /should/ never be used... ksb::Debug::setIPC($ipc); - POSIX::_exit (_handle_monitoring ($ipc, $updaterToMonitorIPC)); + my $exitcode = _handle_monitoring ($ipc, $updaterToMonitorIPC); + if (waitpid ($updaterPid, WNOHANG) == 0) { + error (" r[b[***] updater thread is finished but hasn't exited?!?"); + } + + POSIX::_exit ($exitcode); } } else { # Still the parent, let's do the build. + + # If the user sends SIGHUP during the build, we should allow the current + # module to complete and then exit early. + local $SIG{HUP} = sub { + say "[ build ] recv SIGHUP, will end after this module"; + + # If we haven't recv'd yet, forward to monitor in case user didn't + # send to process group + kill 'HUP', $monitorPid unless $DO_STOP; + $DO_STOP = 1; + }; + + $0 = 'kdesrc-build[build]'; $ipc->setReceiver(); $result = _handle_build ($ipc, $ctx); }