This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
add explicit 1-arg and 3-arg sig handler functions
[perl5.git] / mg.c
diff --git a/mg.c b/mg.c
index fe07755..9424698 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -62,8 +62,9 @@ tie.
 #  include <sys/prctl.h>
 #endif
 
-#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
-Signal_t Perl_csighandler(int sig, siginfo_t *, void *);
+
+#ifdef PERL_USE_3ARG_SIGHANDLER
+Signal_t Perl_csighandler(int sig, Siginfo_t *, void *);
 #else
 Signal_t Perl_csighandler(int sig);
 #endif
@@ -556,12 +557,18 @@ S_mg_free_struct(pTHX_ SV *sv, MAGIC *mg)
     const MGVTBL* const vtbl = mg->mg_virtual;
     if (vtbl && vtbl->svt_free)
        vtbl->svt_free(aTHX_ sv, mg);
-    if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
+
+    if (mg->mg_type == PERL_MAGIC_collxfrm && mg->mg_len >= 0)
+        /* collate magic uses string len not buffer len, so
+         * free even with mg_len == 0 */
+        Safefree(mg->mg_ptr);
+    else if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
        if (mg->mg_len > 0 || mg->mg_type == PERL_MAGIC_utf8)
            Safefree(mg->mg_ptr);
        else if (mg->mg_len == HEf_SVKEY)
            SvREFCNT_dec(MUTABLE_SV(mg->mg_ptr));
     }
+
     if (mg->mg_flags & MGf_REFCOUNTED)
        SvREFCNT_dec(mg->mg_obj);
     Safefree(mg);
@@ -594,7 +601,7 @@ Perl_mg_free(pTHX_ SV *sv)
 }
 
 /*
-=for apidoc Am|void|mg_free_type|SV *sv|int how
+=for apidoc mg_free_type
 
 Remove any magic of type C<how> from the SV C<sv>.  See L</sv_magic>.
 
@@ -818,26 +825,24 @@ S_fixup_errno_string(pTHX_ SV* sv)
          * avoid as many possible backward compatibility issues as possible, we
          * don't turn on the flag unless we have to.  So the flag stays off for
          * an entirely invariant string.  We assume that if the string looks
-         * like UTF-8, it really is UTF-8:  "text in any other encoding that
-         * uses bytes with the high bit set is extremely unlikely to pass a
-         * UTF-8 validity test"
+         * like UTF-8 in a single script, it really is UTF-8:  "text in any
+         * other encoding that uses bytes with the high bit set is extremely
+         * unlikely to pass a UTF-8 validity test"
          * (http://en.wikipedia.org/wiki/Charset_detection).  There is a
          * potential that we will get it wrong however, especially on short
          * error message text, so do an additional check. */
-        if (   ! IN_BYTES  /* respect 'use bytes' */
-            && ! is_utf8_invariant_string((U8*) SvPVX_const(sv), SvCUR(sv))
-            &&   is_utf8_string((U8*) SvPVX_const(sv), SvCUR(sv))
+        if ( ! IN_BYTES  /* respect 'use bytes' */
+            && is_utf8_non_invariant_string((U8*) SvPVX_const(sv), SvCUR(sv))
 
 #ifdef USE_LOCALE_MESSAGES
 
-            &&   _is_cur_LC_category_utf8(LC_MESSAGES)
-
-#elif defined(USE_LOCLAE_CTYPE)
+            &&  _is_cur_LC_category_utf8(LC_MESSAGES)
 
-                 /* For systems that don't have a separate message category,
-                  * this assumes that they follow the CTYPE one */
-            &&   _is_cur_LC_category_utf8(LC_CTYPE)
+#else   /* If can't check directly, at least can see if script is consistent,
+           under UTF-8, which gives us an extra measure of confidence. */
 
+            && isSCRIPT_RUN((const U8 *) SvPVX_const(sv), (U8 *) SvEND(sv),
+                            TRUE) /* Means assume UTF-8 */
 #endif
 
         ) {
@@ -847,7 +852,7 @@ S_fixup_errno_string(pTHX_ SV* sv)
 }
 
 /*
-=for apidoc Am|SV *|sv_string_from_errnum|int errnum|SV *tgtsv
+=for apidoc sv_string_from_errnum
 
 Generates the message string describing an OS error and returns it as
 an SV.  C<errnum> must be a value that C<errno> could take, identifying
@@ -1028,7 +1033,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
        break;
 
     case '\006':               /* ^F */
-       sv_setiv(sv, (IV)PL_maxsysfd);
+        if (nextchar == '\0') {
+            sv_setiv(sv, (IV)PL_maxsysfd);
+        }
+        else if (strEQ(remaining, "EATURE_BITS")) {
+            sv_setuv(sv, PL_compiling.cop_features);
+        }
        break;
     case '\007':               /* ^GLOBAL_PHASE */
        if (strEQ(remaining, "LOBAL_PHASE")) {
@@ -1070,7 +1080,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
         sv_setiv(sv, (IV)PL_perldb);
        break;
     case '\023':               /* ^S */
-        {
+       if (nextchar == '\0') {
            if (PL_parser && PL_parser->lex_state != LEX_NOTPARSING)
                SvOK_off(sv);
            else if (PL_in_eval)
@@ -1078,6 +1088,18 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg)
            else
                sv_setiv(sv, 0);
        }
+       else if (strEQ(remaining, "AFE_LOCALES")) {
+
+#if ! defined(USE_ITHREADS) || defined(USE_THREAD_SAFE_LOCALE)
+
+           sv_setuv(sv, (UV) 1);
+
+#else
+           sv_setuv(sv, (UV) 0);
+
+#endif
+
+        }
        break;
     case '\024':               /* ^T */
        if (nextchar == '\0') {
@@ -1465,19 +1487,45 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg)
     return sv_unmagic(sv, mg->mg_type);
 }
 
+
+#ifdef PERL_USE_3ARG_SIGHANDLER
 Signal_t
-#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
-Perl_csighandler(int sig, siginfo_t *sip PERL_UNUSED_DECL, void *uap PERL_UNUSED_DECL)
+Perl_csighandler(int sig, Siginfo_t *sip, void *uap)
+{
+    Perl_csighandler3(sig, sip, uap);
+}
 #else
+Signal_t
 Perl_csighandler(int sig)
+{
+    Perl_csighandler3(sig, NULL, NULL);
+}
 #endif
+
+Signal_t
+Perl_csighandler1(int sig)
+{
+    Perl_csighandler3(sig, NULL, NULL);
+}
+
+/* Handler intended to directly handle signal calls from the kernel.
+ * (Depending on configuration, the kernel may actually call one of the
+ * wrappers csighandler() or csighandler1() instead.)
+ * It either queues up the signal or dispatches it immediately depending
+ * on whether safe signals are enabled and whether the signal is capable
+ * of being deferred (e.g. SEGV isn't).
+ */
+
+Signal_t
+Perl_csighandler3(int sig, Siginfo_t *sip PERL_UNUSED_DECL, void *uap PERL_UNUSED_DECL)
 {
 #ifdef PERL_GET_SIG_CONTEXT
     dTHXa(PERL_GET_SIG_CONTEXT);
 #else
     dTHX;
 #endif
-#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
+
+#ifdef PERL_USE_3ARG_SIGHANDLER
 #if defined(__cplusplus) && defined(__GNUC__)
     /* g++ doesn't support PERL_UNUSED_DECL, so the sip and uap
      * parameters would be warned about. */
@@ -1485,6 +1533,7 @@ Perl_csighandler(int sig)
     PERL_UNUSED_ARG(uap);
 #endif
 #endif
+
 #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
     (void) rsignal(sig, PL_csighandlerp);
     if (PL_sig_ignoring[sig]) return;
@@ -1510,11 +1559,20 @@ Perl_csighandler(int sig)
           (PL_signals & PERL_SIGNALS_UNSAFE_FLAG))
        /* Call the perl level handler now--
         * with risk we may be in malloc() or being destructed etc. */
-#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
-       (*PL_sighandlerp)(sig, NULL, NULL);
+    {
+        if (PL_sighandlerp == Perl_sighandler)
+            /* default handler, so can call perly_sighandler() directly
+             * rather than via Perl_sighandler, passing the extra
+             * 'safe = false' arg
+             */
+            Perl_perly_sighandler(sig, NULL, NULL, 0 /* unsafe */);
+        else
+#ifdef PERL_USE_3ARG_SIGHANDLER
+            (*PL_sighandlerp)(sig, NULL, NULL);
 #else
-       (*PL_sighandlerp)(sig);
+            (*PL_sighandlerp)(sig);
 #endif
+    }
     else {
        if (!PL_psig_pend) return;
        /* Set a flag to say this signal is pending, that is awaiting delivery after
@@ -1592,11 +1650,19 @@ Perl_despatch_signals(pTHX)
            }
 #endif
            PL_psig_pend[sig] = 0;
-#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
-           (*PL_sighandlerp)(sig, NULL, NULL);
+            if (PL_sighandlerp == Perl_sighandler)
+                /* default handler, so can call perly_sighandler() directly
+                 * rather than via Perl_sighandler, passing the extra
+                 * 'safe = true' arg
+                 */
+                Perl_perly_sighandler(sig, NULL, NULL, 1 /* safe */);
+            else
+#ifdef PERL_USE_3ARG_SIGHANDLER
+                (*PL_sighandlerp)(sig, NULL, NULL);
 #else
-           (*PL_sighandlerp)(sig);
+                (*PL_sighandlerp)(sig);
 #endif
+
 #ifdef HAS_SIGPROCMASK
            if (!was_blocked)
                LEAVE;
@@ -1912,8 +1978,8 @@ Perl_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, SV *meth, U32 flags,
        va_start(args, argc);
 
        do {
-           SV *const sv = va_arg(args, SV *);
-           PUSHs(sv);
+           SV *const this_sv = va_arg(args, SV *);
+           PUSHs(this_sv);
        } while (--argc);
 
        va_end(args);
@@ -2517,6 +2583,15 @@ Perl_vivify_defelem(pTHX_ SV *sv)
 }
 
 int
+Perl_magic_setnonelem(pTHX_ SV *sv, MAGIC *mg)
+{
+    PERL_ARGS_ASSERT_MAGIC_SETNONELEM;
+    PERL_UNUSED_ARG(mg);
+    sv_unmagic(sv, PERL_MAGIC_nonelem);
+    return 0;
+}
+
+int
 Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg)
 {
     PERL_ARGS_ASSERT_MAGIC_KILLBACKREFS;
@@ -2815,7 +2890,12 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
             Perl_croak(aTHX_ "${^ENCODING} is no longer supported");
        break;
     case '\006':       /* ^F */
-       PL_maxsysfd = SvIV(sv);
+        if (mg->mg_ptr[1] == '\0') {
+            PL_maxsysfd = SvIV(sv);
+        }
+        else if (strEQ(mg->mg_ptr + 1, "EATURE_BITS")) {
+            PL_compiling.cop_features = SvUV(sv);
+        }
        break;
     case '\010':       /* ^H */
         {
@@ -2897,6 +2977,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) {
            if ( ! (PL_dowarn & G_WARN_ALL_MASK)) {
                if (!SvPOK(sv)) {
+                    if (!specialWARN(PL_compiling.cop_warnings))
+                        PerlMemShared_free(PL_compiling.cop_warnings);
                    PL_compiling.cop_warnings = pWARN_STD;
                    break;
                }
@@ -3051,7 +3133,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
 #else
 #   define PERL_VMS_BANG 0
 #endif
-#if defined(WIN32) && ! defined(UNDER_CE)
+#if defined(WIN32)
        SETERRNO(win32_get_errno(SvIOK(sv) ? SvIVX(sv) : SvOK(sv) ? sv_2iv(sv) : 0),
                 (SvIV(sv) == EVMSERR) ? 4 : PERL_VMS_BANG);
 #else
@@ -3151,7 +3233,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
        {
            const char *p = SvPV_const(sv, len);
             Groups_t *gary = NULL;
-            const char* endptr;
+            const char* p_end = p + len;
+            const char* endptr = p_end;
             UV uv;
 #ifdef _SC_NGROUPS_MAX
            int maxgrp = sysconf(_SC_NGROUPS_MAX);
@@ -3174,6 +3257,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                 if (endptr == NULL)
                     break;
                 p = endptr;
+                endptr = p_end;
                 while (isSPACE(*p))
                     ++p;
                 if (!*p)
@@ -3278,12 +3362,62 @@ Perl_whichsig_pvn(pTHX_ const char *sig, STRLEN len)
     return -1;
 }
 
+
+/* Perl_sighandler(), Perl_sighandler1(), Perl_sighandler3():
+ * these three function are intended to be called by the OS as 'C' level
+ * signal handler functions in the case where unsafe signals are being
+ * used - i.e. they immediately invoke Perl_perly_sighandler() to call the
+ * perl-level sighandler, rather than deferring.
+ * In fact, the core itself will normally use Perl_csighandler as the
+ * OS-level handler; that function will then decide whether to queue the
+ * signal or call Perl_sighandler / Perl_perly_sighandler itself. So these
+ * functions are more useful for e.g. POSIX.xs when it wants explicit
+ * control of what's happening.
+ */
+
+
+#ifdef PERL_USE_3ARG_SIGHANDLER
+
 Signal_t
-#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
-Perl_sighandler(int sig, siginfo_t *sip, void *uap)
+Perl_sighandler(int sig, Siginfo_t *sip, void *uap)
+{
+    Perl_perly_sighandler(sig, sip, uap, 0);
+}
+
 #else
+
+Signal_t
 Perl_sighandler(int sig)
+{
+    Perl_perly_sighandler(sig, NULL, NULL, 0);
+}
+
 #endif
+
+Signal_t
+Perl_sighandler1(int sig)
+{
+    Perl_perly_sighandler(sig, NULL, NULL, 0);
+}
+
+Signal_t
+Perl_sighandler3(int sig, Siginfo_t *sip PERL_UNUSED_DECL, void *uap PERL_UNUSED_DECL)
+{
+    Perl_perly_sighandler(sig, sip, uap, 0);
+}
+
+
+/* Invoke the perl-level signal handler. This function is called either
+ * directly from one of the C-level signals handlers (Perl_sighandler or
+ * Perl_csighandler), or for safe signals, later from
+ * Perl_despatch_signals() at a suitable safe point during execution.
+ *
+ * 'safe' is a boolean indicating the latter call path.
+ */
+
+Signal_t
+Perl_perly_sighandler(int sig, Siginfo_t *sip PERL_UNUSED_DECL,
+                    void *uap PERL_UNUSED_DECL, bool safe)
 {
 #ifdef PERL_GET_SIG_CONTEXT
     dTHXa(PERL_GET_SIG_CONTEXT);
@@ -3415,10 +3549,13 @@ Perl_sighandler(int sig)
         * blocked by the system when we entered.
         */
 #ifdef HAS_SIGPROCMASK
-#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
-           if (sip || uap)
-#endif
-           {
+           if (!safe) {
+                /* safe signals called via dispatch_signals() set up a
+                 * savestack destructor, unblock_sigmask(), to
+                 * automatically unblock the handler at the end. If
+                 * instead we get here directly, we have to do it
+                 * ourselves
+                 */
                sigset_t set;
                sigemptyset(&set);
                sigaddset(&set,sig);
@@ -3426,6 +3563,9 @@ Perl_sighandler(int sig)
            }
 #else
            /* Not clear if this will work */
+            /* XXX not clear if this should be protected by 'if (safe)'
+             * too */
+
            (void)rsignal(sig, SIG_IGN);
            (void)rsignal(sig, PL_csighandlerp);
 #endif