title: What's the most reliable method for cross-platform alarm signal handling or execution timeouts in Perl?
body: <p>I've added advisory locking to <a href="https://sqitch.org" rel="nofollow noreferrer">Sqitch</a>, using <a href="https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS" rel="nofollow noreferrer">Postgres advisory locks</a> and <a href="https://dev.mysql.com/doc/refman/8.0/en/locking-functions.html" rel="nofollow noreferrer">MySQL GET_LOCK()</a>. This feature prevents more than one instance of Sqitch from deploying to a database at one time. This works great, but I wanted to add a lock timeout, too, so that one never finds a CI/CD process hung for hours or days because something went amiss.</p>
  <p>MySQL's <code>GET_LOCK()</code> supports a timeout argument, but Postgres advisory locks do not. Since I thought it likely that other database engines would also not have timeouts, I thought it best to implement the timeout in Perl. Following the DBI manual, I used <a href="https://metacpan.org/pod/Sys::SigAction" rel="nofollow noreferrer">Sys::SigAction</a> to set and handle <a href="https://github.com/sqitchers/sqitch/blob/e75292994b69448ca9b039ab93881584823595e1/lib/App/Sqitch/Engine.pm#L1043-L1047" rel="nofollow noreferrer">the timeout</a>:</p>
  <pre class="lang-perl prettyprint-override"><code># Try waiting for the lock.
  require App::Sqitch::SigAction;
  return $self-&gt;_locked(1) unless App::Sqitch::SigAction::timeout_call($wait, sub {
      $self-&gt;wait_lock
  });
  </code></pre>
  <p>I also added <a href="https://github.com/sqitchers/sqitch/blob/e75292994b69448ca9b039ab93881584823595e1/t/lib/DBIEngineTest.pm#L1748-L1762" rel="nofollow noreferrer">tests</a> to confirm it works with both MySQL and Postgres. So far so good.</p>
  <p>Alas, Sys::SigAction <a href="https://github.com/labaxter/sys-sigaction/blob/3c6112c7a26efbdffd0745d89fd70a0eeebca0da/Makefile.PL#L11-L25" rel="nofollow noreferrer">does not work on Windows</a>. I took a stab and <a href="https://github.com/theory/sys-sigaction/runs/3900853084" rel="nofollow noreferrer">testing it on Windows</a>, but since Windows Perl is not compiled with <code>d_sigaction</code>, which <a href="https://github.com/labaxter/sys-sigaction/blob/3c6112c7a26efbdffd0745d89fd70a0eeebca0da/Makefile.PL#L48-L57" rel="nofollow noreferrer">Sys::SigAction also requires</a>, I didn't get far. I tried implementing the <a href="https://perldoc.perl.org/functions/alarm" rel="nofollow noreferrer">Perl-standard <code>alarm</code>/<code>$SIG{ALRM}</code> pattern</a>, but it failed to send the signal while waiting on the Postgres lock.</p>
  <p>Which has led me here and to my question: What is the best cross-platform pattern for timing out some execution in Perl? Ideally it has a straight-forward interface, works on *nix and Windows, and effectively handles breaking out of a database query.</p>