summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pod/perldiag.pod5
-rw-r--r--pp_sys.c31
-rw-r--r--t/lib/warnings/pp_sys9
3 files changed, 38 insertions, 7 deletions
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index 1d53e5df92..558fd62428 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -7099,6 +7099,11 @@ You likely need to figure out how this multi-byte character got mixed up
with your single-byte locale (or perhaps you thought you had a UTF-8
locale, but Perl disagrees).
+=item %s() with negative argument
+
+(S misc) Certain operations make no sense with negative arguments.
+Warning is given and the operation is not done.
+
=item Within []-length '%c' not allowed
(F) The count in the (un)pack template may be replaced by C<[TEMPLATE]>
diff --git a/pp_sys.c b/pp_sys.c
index 6770063267..b92f001731 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -4708,13 +4708,30 @@ PP(pp_alarm)
{
#ifdef HAS_ALARM
dSP; dTARGET;
- int anum;
- anum = POPi;
- anum = alarm((unsigned int)anum);
- if (anum < 0)
- RETPUSHUNDEF;
- PUSHi(anum);
- RETURN;
+ /* alarm() takes an unsigned int number of seconds, and return the
+ * unsigned int number of seconds remaining in the previous alarm
+ * (alarms don't stack). Therefore negative return values are not
+ * possible. */
+ int anum = POPi;
+ if (anum < 0) {
+ /* Note that while the C library function alarm() as such has
+ * no errors defined (or in other words, properly behaving client
+ * code shouldn't expect any), alarm() being obsoleted by
+ * setitimer() and often being implemented in terms of
+ * setitimer(), can fail. */
+ /* diag_listed_as: %s() with negative argument */
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_MISC),
+ "alarm() with negative argument");
+ SETERRNO(EINVAL, LIB_INVARG);
+ RETPUSHUNDEF;
+ }
+ else {
+ unsigned int retval = alarm(anum);
+ if ((int)retval < 0) /* Strictly speaking "cannot happen". */
+ RETPUSHUNDEF;
+ PUSHu(retval);
+ RETURN;
+ }
#else
DIE(aTHX_ PL_no_func, "alarm");
#endif
diff --git a/t/lib/warnings/pp_sys b/t/lib/warnings/pp_sys
index 0dce57f9a5..1100cf2bcb 100644
--- a/t/lib/warnings/pp_sys
+++ b/t/lib/warnings/pp_sys
@@ -921,3 +921,12 @@ gmtime(NaN) too large at - line 6.
gmtime(NaN) failed at - line 6.
localtime(NaN) too large at - line 7.
localtime(NaN) failed at - line 7.
+
+########
+# pp_sys.c [pp_alarm]
+alarm(-1);
+no warnings "misc";
+alarm(-1);
+
+EXPECT
+alarm() with negative argument at - line 2.