This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Store struct termios used by POSIX::Termios directly in the object SV.
authorNicholas Clark <nick@ccl4.org>
Wed, 7 Sep 2011 11:15:04 +0000 (13:15 +0200)
committerNicholas Clark <nick@ccl4.org>
Tue, 13 Sep 2011 09:28:07 +0000 (11:28 +0200)
Previously POSIX::Termios was using the PTROBJ typemap to store a pointer to
a dynamically-allocated struct termios as an IV (blessed into the class).
This requires an explicit DESTROY to free the dynamic allocation, but fails
badly if any POSIX::Termios objects exist at ithread clone time, as the
dynamic allocation is not duplicated in the new thread. (DESTROY is called
in both threads, free-from-wrong pool or other jollity occurs.)

Removing dynamic allocation removes the need for a DESTROY method.

This introduces a new OPAQUEPTROBJ typemap, but currently doesn't use the
OUTPUT section, as that copies an existing structure, whereas
POSIX::Termios->new() only needs to zero-allocate the right space. Assuming
that this typemap should be of general applicability, it should be moved to
the main typemap file.

ext/POSIX/POSIX.xs
ext/POSIX/typemap

index 41f53d9..f293553 100644 (file)
@@ -712,30 +712,28 @@ sigismember(sigset, sig)
 
 MODULE = Termios       PACKAGE = POSIX::Termios        PREFIX = cf
 
-POSIX::Termios
+void
 new(packname = "POSIX::Termios", ...)
     const char *       packname
     CODE:
        {
 #ifdef I_TERMIOS
-           Newx(RETVAL, 1, struct termios);
+           SV *t;
+           ST(0) = sv_newmortal();
+           t = newSVrv(ST(0), packname);
+           sv_grow(t, sizeof(struct termios) + 1);
+           SvCUR_set(t, sizeof(struct termios));
+           SvPOK_on(t);
+           /* The previous implementation stored a pointer to an uninitialised
+              struct termios. Seems safer to initialise it, particularly as
+              this implementation exposes the struct to prying from perl-space.
+           */
+           memset(SvPVX(t), 0, 1 + sizeof(struct termios));
+           XSRETURN(1);
 #else
            not_here("termios");
-        RETVAL = 0;
 #endif
        }
-    OUTPUT:
-       RETVAL
-
-void
-DESTROY(termios_ref)
-       POSIX::Termios  termios_ref
-    CODE:
-#ifdef I_TERMIOS
-       Safefree(termios_ref);
-#else
-           not_here("termios");
-#endif
 
 SysRet
 getattr(termios_ref, fd = 0)
index d54d5d1..b283099 100644 (file)
@@ -12,5 +12,19 @@ speed_t                      T_IV
 tcflag_t               T_IV
 cc_t                   T_IV
 POSIX::SigSet          T_PTROBJ
-POSIX::Termios         T_PTROBJ
+POSIX::Termios         T_OPAQUEPTROBJ
 POSIX::SigAction       T_HVREF
+
+INPUT
+T_OPAQUEPTROBJ
+       if (SvROK($arg) && sv_derived_from($arg, \"${ntype}\")) {
+           $var = ($type)SvPV_nolen(SvRV($arg));
+       }
+       else
+           Perl_croak(aTHX_ \"%s: %s is not of type %s\",
+                       ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+                       \"$var\", \"$ntype\")
+
+OUTPUT
+T_OPAQUEPTROBJ
+       sv_setref_pvn($arg, \"${ntype}\", (const char*)$var, sizeof(*$var));