From 09669b94dcfcb20c354f454f34c1445a260e2980 Mon Sep 17 00:00:00 2001 From: John Darrington Date: Wed, 7 Jan 2009 10:16:03 +0900 Subject: [PATCH] Ensure that dict survives sysfile 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 | 12 ++++++++++-- perl-module/t/Pspp.t | 29 ++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/perl-module/PSPP.xs b/perl-module/PSPP.xs index b468cc74..6373bc37 100644 --- a/perl-module/PSPP.xs +++ b/perl-module/PSPP.xs @@ -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 diff --git a/perl-module/t/Pspp.t b/perl-module/t/Pspp.t index ed824d12..ff0e4d1e 100644 --- a/perl-module/t/Pspp.t +++ b/perl-module/t/Pspp.t @@ -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 ); -- 2.30.2