@@ -804,20 +804,31 @@ void fwriteMain(fwriteMainArgs args)
804804 if (args .is_gzip ) {
805805 // alloc zlib streams
806806 thread_streams = (z_stream * ) malloc (nth * sizeof (z_stream ));
807+ if (!thread_streams ) {
808+ // # nocov start
809+ free (buffPool );
810+ STOP (_ ("Failed to allocated %d bytes for threads_streams." ), (int )(nth * sizeof (z_stream )));
811+ // # nocov end
812+ }
807813 if (verbose ) {
808814 DTPRINT (_ ("Allocate %zu bytes for thread_streams\n" ), nth * sizeof (z_stream ));
809815 }
810- if (!thread_streams )
811- STOP (_ ("Failed to allocated %d bytes for threads_streams." ), (int )(nth * sizeof (z_stream ))); // #nocov
812816 // VLA on stack should be fine for nth structs; in zlib v1.2.11 sizeof(struct)==112 on 64bit
813817 // not declared inside the parallel region because solaris appears to move the struct in
814818 // memory when the #pragma omp for is entered, which causes zlib's internal self reference
815819 // pointer to mismatch, #4099
816820
817821 // compute zbuffSize which is the same for each thread
818822 z_stream * stream = thread_streams ;
819- if (init_stream (stream ) != Z_OK )
820- STOP (_ ("Can't init stream structure for deflateBound" )); // #nocov
823+ if (init_stream (stream ) != Z_OK ) {
824+ // # nocov start
825+ free (buffPool );
826+ #ifndef NOZLIB
827+ free (thread_streams );
828+ #endif
829+ STOP (_ ("Can't init stream structure for deflateBound" ));
830+ // # nocov end
831+ }
821832 zbuffSize = deflateBound (stream , buffSize );
822833 if (verbose )
823834 DTPRINT (_ ("zbuffSize=%d returned from deflateBound\n" ), (int )zbuffSize );
@@ -832,6 +843,9 @@ void fwriteMain(fwriteMainArgs args)
832843 if (!zbuffPool ) {
833844 // # nocov start
834845 free (buffPool );
846+ #ifndef NOZLIB
847+ free (thread_streams );
848+ #endif
835849 STOP (_ ("Unable to allocate %zu MiB * %d thread compressed buffers; '%d: %s'. Please read ?fwrite for nThread, buffMB and verbose options." ),
836850 zbuffSize / MEGA , nth , errno , strerror (errno ));
837851 // # nocov end
@@ -880,11 +894,18 @@ void fwriteMain(fwriteMainArgs args)
880894 DTPRINT ("%s" , buff );
881895 } else {
882896 int ret0 = 0 , ret1 = 0 , ret2 = 0 ;
883- if (args .is_gzip ) {
884897#ifndef NOZLIB
898+ if (args .is_gzip ) {
885899 z_stream * stream = thread_streams ;
886- if (init_stream (stream ) != Z_OK )
887- STOP (_ ("Can't init stream structure for writing header" )); // #nocov
900+ if (init_stream (stream ) != Z_OK ) {
901+ // # nocov start
902+ free (buffPool );
903+ #ifndef NOZLIB
904+ free (thread_streams );
905+ free (zbuffPool );
906+ #endif
907+ STOP (_ ("Can't init stream structure for writing header" ));
908+ }
888909 char * zbuff = zbuffPool ;
889910 // write minimal gzip header
890911 char * header = "\037\213\10\0\0\0\0\0\0\3" ;
@@ -900,14 +921,21 @@ void fwriteMain(fwriteMainArgs args)
900921 ret2 = WRITE (f , zbuff , (int )zbuffUsed );
901922 compress_len += zbuffUsed ;
902923 }
903- #endif
904924 } else {
925+ #endif
905926 ret2 = WRITE (f , buff , (int )(ch - buff ));
927+ #ifndef NOZLIB
906928 }
929+ #endif
907930 if (ret0 == -1 || ret1 || ret2 == -1 ) {
908931 // # nocov start
909932 int errwrite = errno ; // capture write errno now in case close fails with a different errno
910933 CLOSE (f );
934+ free (buffPool );
935+ #ifndef NOZLIB
936+ free (thread_streams );
937+ free (zbuffPool );
938+ #endif
911939 if (ret0 == -1 ) STOP (_ ("Can't write gzip header error: %d" ), ret0 );
912940 else if (ret1 ) STOP (_ ("Compress gzip error: %d" ), ret1 );
913941 else STOP (_ ("%s: '%s'" ), strerror (errwrite ), args .filename );
@@ -922,8 +950,15 @@ void fwriteMain(fwriteMainArgs args)
922950 if (args .nrow == 0 ) {
923951 if (verbose )
924952 DTPRINT (_ ("No data rows present (nrow==0)\n" ));
925- if (f != -1 && CLOSE (f ))
926- STOP (_ ("%s: '%s'" ), strerror (errno ), args .filename ); // # nocov
953+ if (f != -1 && CLOSE (f )) {
954+ // # nocov start
955+ free (buffPool );
956+ #ifndef NOZLIB
957+ free (thread_streams );
958+ free (zbuffPool );
959+ #endif
960+ STOP (_ ("%s: '%s'" ), strerror (errno ), args .filename );
961+ }
927962 return ;
928963 }
929964
@@ -1023,25 +1058,27 @@ void fwriteMain(fwriteMainArgs args)
10231058 if (f == -1 ) {
10241059 * ch = '\0' ; // standard C string end marker so DTPRINT knows where to stop
10251060 DTPRINT ("%s" , myBuff );
1026- } else if ( args . is_gzip ) {
1061+ } else
10271062#ifndef NOZLIB
1028- ret = WRITE (f , myzBuff , (int )myzbuffUsed );
1029- compress_len += myzbuffUsed ;
1063+ if (args .is_gzip ) {
1064+ ret = WRITE (f , myzBuff , (int )myzbuffUsed );
1065+ compress_len += myzbuffUsed ;
1066+ } else
10301067#endif
1031- } else {
1068+ {
10321069 ret = WRITE (f , myBuff , (int )(ch - myBuff ));
10331070 }
10341071 if (ret == -1 ) {
10351072 failed = true; // # nocov
10361073 failed_write = errno ; // # nocov
10371074 }
10381075
1039- if (args .is_gzip ) {
10401076#ifndef NOZLIB
1077+ if (args .is_gzip ) {
10411078 crc = crc32_combine (crc , mycrc , mylen );
10421079 len += mylen ;
1043- #endif
10441080 }
1081+ #endif
10451082
10461083 int used = 100 * ((double )(ch - myBuff )) / buffSize ; // percentage of original buffMB
10471084 if (used > maxBuffUsedPC )
@@ -1067,36 +1104,35 @@ void fwriteMain(fwriteMainArgs args)
10671104 }
10681105 }
10691106 }
1070- if (args .is_gzip ) {
10711107#ifndef NOZLIB
1108+ if (args .is_gzip ) {
10721109 deflateEnd (mystream );
1073- #endif
10741110 }
1111+ #endif
10751112
10761113 } // end of parallel for loop
10771114
1078- /* put a 4-byte integer into a byte array in LSB order */
1079- #define PUT4 (a ,b ) ((a)[0]=(b), (a)[1]=(b)>>8, (a)[2]=(b)>>16, (a)[3]=(b)>>24)
1080-
1081- // write gzip tailer with crc and len
1082- if (args .is_gzip ) {
1083- #ifndef NOZLIB
1084- unsigned char tail [10 ];
1085- tail [0 ] = 3 ;
1086- tail [1 ] = 0 ;
1087- PUT4 (tail + 2 , crc );
1088- PUT4 (tail + 6 , len );
1089- int ret = WRITE (f , tail , 10 );
1090- compress_len += 10 ;
1091- if (ret == -1 )
1092- STOP ("Error: can't write gzip tailer" ); // # nocov
1093- #endif
1094- }
1095-
10961115 free (buffPool );
1116+
10971117#ifndef NOZLIB
10981118 free (thread_streams );
10991119 free (zbuffPool );
1120+
1121+ /* put a 4-byte integer into a byte array in LSB order */
1122+ #define PUT4 (a ,b ) ((a)[0]=(b), (a)[1]=(b)>>8, (a)[2]=(b)>>16, (a)[3]=(b)>>24)
1123+
1124+ // write gzip tailer with crc and len
1125+ if (args .is_gzip ) {
1126+ unsigned char tail [10 ];
1127+ tail [0 ] = 3 ;
1128+ tail [1 ] = 0 ;
1129+ PUT4 (tail + 2 , crc );
1130+ PUT4 (tail + 6 , len );
1131+ int ret = WRITE (f , tail , 10 );
1132+ compress_len += 10 ;
1133+ if (ret == -1 )
1134+ STOP ("Error: can't write gzip tailer" ); // # nocov
1135+ }
11001136#endif
11011137
11021138 // Finished parallel region and can call R API safely now.
@@ -1112,12 +1148,12 @@ void fwriteMain(fwriteMainArgs args)
11121148 }
11131149
11141150 if (verbose ) {
1115- if (args .is_gzip ) {
11161151#ifndef NOZLIB
1152+ if (args .is_gzip ) {
11171153 DTPRINT ("zlib: uncompressed length=%zu (%zu MiB), compressed length=%zu (%zu MiB), ratio=%.1f%%, crc=%x\n" ,
11181154 len , len / MEGA , compress_len , compress_len / MEGA , len != 0 ? (100.0 * compress_len ) / len : 0 , crc );
1119- #endif
11201155 }
1156+ #endif
11211157 DTPRINT ("Written %" PRId64 " rows in %.3f secs using %d thread%s. MaxBuffUsed=%d%%\n" ,
11221158 args .nrow , 1.0 * (wallclock ()- t0 ), nth , nth == 1 ? "" : "s" , maxBuffUsedPC );
11231159 }
0 commit comments