[sdk/kdesrc-build] /: Support SIGHUP for graceful script exit.

Michael Pyne null at kde.org
Thu Jul 14 05:13:53 BST 2022


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 <mpyne at kde.org>
+    Copyright (c) 2005-2008, 2010-2022 Michael Pyne <mpyne at kde.org>
 
     Copyright (c) 2005 Carlos Leonhard Woelz <carloswoelz at imap-mail.com>
     Copyright (c) 2009 Burkhard Lück <lueck at 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 <mpyne at kde.org>
+    Copyright (c) 2011, 2014-2020, 2022 Michael Pyne <mpyne at 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);
     }


More information about the kde-doc-english mailing list