Ensure that dict survives sysfile
authorJohn Darrington <john@darrington.wattle.id.au>
Wed, 7 Jan 2009 01:16:03 +0000 (10:16 +0900)
committerJohn Darrington <john@darrington.wattle.id.au>
Wed, 7 Jan 2009 01:16:03 +0000 (10:16 +0900)
Make sure that the dict of a sysfile survives for the
lifetime of that sysfile.  Thanks to Rob Messer for
reporting this bug.

perl-module/PSPP.xs
perl-module/t/Pspp.t

index b468cc7467325a322378ad5970d19eb2b8a12b21..6373bc37dea1c4fa540c19315743900f47ef80d3 100644 (file)
@@ -55,6 +55,9 @@ struct sysfile_info
 
   /* A pointer to the dictionary. Owned externally */
   const struct dictionary *dict;
+
+  /* The scalar containing the dictionary */
+  SV *dict_sv;
 };
 
 
@@ -454,11 +457,13 @@ MODULE = PSPP             PACKAGE = PSPP::Sysfile
 
 
 struct sysfile_info *
-pxs_create_sysfile (name, dict, opts_hr)
+pxs_create_sysfile (name, dict_ref, opts_hr)
  char *name
- struct dictionary *dict
+ SV *dict_ref
  SV *opts_hr
 INIT:
+ SV *dict_sv = SvRV (dict_ref);
+ struct dictionary *dict = (void *) SvIV (dict_sv);
  struct sfm_write_options opts;
  if (!SvROK (opts_hr))
   {
@@ -482,6 +487,8 @@ CODE:
  sfi->writer = sfm_open_writer (fh, dict, opts);
  sfi->dict = dict;
  sfi->opened = true;
+ sfi->dict_sv = dict_sv;
+ SvREFCNT_inc (sfi->dict_sv);
  
  RETVAL = sfi;
  OUTPUT:
@@ -500,6 +507,7 @@ DESTROY (sfi)
  struct sysfile_info *sfi
 CODE:
  sysfile_close (sfi);
+ SvREFCNT_dec (sfi->dict_sv);
  free (sfi);
 
 int
index ed824d12cc476fdda08dcaad3aae5473fdabff2a..ff0e4d1e0dac22d277a28f95d606398bbb637485 100644 (file)
@@ -6,7 +6,7 @@
 
 # change 'tests => 1' to 'tests => last_test_to_print';
 
-use Test::More tests => 30;
+use Test::More tests => 31;
 use Text::Diff;
 use File::Temp qw/ tempfile tempdir /;
 BEGIN { use_ok('PSPP') };
@@ -322,6 +322,33 @@ RESULT
 }
 
 
+# Test to make sure that the dictionary survives the sysfile.
+# Thanks to Rob Messer for reporting this problem
+{
+    my $tempdir = tempdir( CLEANUP => 1 );
+    my $tempfile = "$tempdir/testfile.sav";
+    my $sysfile ;
+
+    {
+       my $d = PSPP::Dict->new();
+
+       PSPP::Var->new ($d, "id",
+                       (
+                        fmt=>PSPP::Fmt::F, 
+                        width=>2, 
+                        decimals=>0
+                        )
+                       );
+
+       $sysfile = PSPP::Sysfile->new ("$tempfile", $d);
+    }
+
+    my $res = $sysfile->append_case ([3]);
+
+    ok ($res, "Dictionary survives sysfile");
+}
+
+
 # Basic reader test
 {
  my $tempdir = tempdir( CLEANUP => 1 );