From patchwork Mon Dec 11 03:55:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerry DeLisle X-Patchwork-Id: 846767 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-468884-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="WBIuAzzG"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yw8Hv09q3z9s7f for ; Mon, 11 Dec 2017 14:55:35 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=LKNZ7kwNEcxFWFqo7B/bZ7gzlZj6I7NoQgOxRknZGV06hqiMni FASdS5eCdmkYPHJDPso+l/1pA5km9vDAb4YzIAjej8zoRubamEc6VVbYeSFPDP59 fiq2kErxk0/V7WEDYGQCk5JsQZrmlykldTilmrSNmlc7nmUZ/nZiGh2m8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=XN3mNaAxqakZidswtbISWgt5z/A=; b=WBIuAzzG7wBBDDswjLEM NHcAkc/etN4CsfgVWABz1Id6zvJ04aYNZsrJkv7XjFoHXCZ+SDqcPOyvJGVEQ/QO fueZnJWajK2j2u4yWDcWLpQ1IzDKPJm6oyI8Z7qBYcvd4XYuaxrQZioyKJONEdo/ 1OlMbclUdbtod+FvAtrwlFU= Received: (qmail 108194 invoked by alias); 11 Dec 2017 03:55:23 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 108173 invoked by uid 89); 11 Dec 2017 03:55:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.8 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_NUMSUBJECT, RCVD_IN_DNSWL_LOW, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=Jerry, existence, automatic, sk:jvdelis X-Spam-User: qpsmtpd, 2 recipients X-HELO: mtaout005-public.msg.strl.va.charter.net Received: from mtaout005-public.msg.strl.va.charter.net (HELO mtaout005-public.msg.strl.va.charter.net) (68.114.190.30) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 11 Dec 2017 03:55:20 +0000 Received: from impout004 ([68.114.189.19]) by mtaout005.msg.strl.va.charter.net (InterMail vM.9.00.023.01 201-2473-194) with ESMTP id <20171211035519.MZHT7356.mtaout005.msg.strl.va.charter.net@impout004>; Sun, 10 Dec 2017 21:55:19 -0600 Received: from [192.168.1.5] ([96.41.213.35]) by impout004 with charter.net id kTvJ1w0030mPCJg01TvJpy; Sun, 10 Dec 2017 21:55:19 -0600 X-Authority-Analysis: v=2.2 cv=EdC4eLuC c=1 sm=1 tr=0 a=NNeuWy7OTYa7gJ+3pFFB5Q==:117 a=NNeuWy7OTYa7gJ+3pFFB5Q==:17 a=x7bEGLp0ZPQA:10 a=r77TgQKjGQsHNAKrUKIA:9 a=mDV3o1hIAAAA:8 a=633Qn5rOTsr6PUkff4IA:9 a=QEXdDO2ut3YA:10 a=ToS7ciofQF_kdAk-s6cA:9 a=hquHOILUSkIA:10 a=_FVE-zBwftR9WsbkzFJk:22 X-Auth-id: anZkZWxpc2xlQGNoYXJ0ZXIubmV0 To: gfortran Cc: gcc patches From: Jerry DeLisle Subject: [patch, libgfortran] Memory issues related to PR78549 Message-ID: <36391954-3ca0-34ee-85d2-c9196a3aeee3@charter.net> Date: Sun, 10 Dec 2017 19:55:17 -0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0 MIME-Version: 1.0 Hi all, While doing addition testing for the subject mentioned PR I discovered numerous un-freed memory allocations. I reported the problem in comment 30 of the PR. The attached patch cleans this up by opening the internal unit structures during program initialization and allowing the automatic closure similar to pre-connected units. The internal stream structures are created and freed at the beginning and end of each I/O operation. I fix a few loose ends. Regression tested on x86_64. OK for trunk? Also needed for same issue in 7. Regards, Jerry 2017-12-11 Jerry DeLisle PR libgfortran/78549 * io/inquire.c (inquire_via_unit): Adjust test for existence for pre-connected internal units. * io/transfer.c (finalize_transfer): When done with a transfer to internal units, free the format buffer and close the stream. (st_read_done): Delete freeing the stream, now handled using sclose in finalize_transfer. (st_write_done): Likewise. * io/unit.c (get_unit): Return NULL for special reserved unit numbers, signifying not accessible to the user. (init_units): Insert the two special internal units into the unit treap. This makes these unit structures available without further allocations for later use by internal unit I/O. These units are automatically deleted by normal program termination. * unix.c (mem_close): Add a guard check to protect from double free. diff --git a/libgfortran/io/inquire.c b/libgfortran/io/inquire.c index 848a08f6157..6ba1224d77c 100644 --- a/libgfortran/io/inquire.c +++ b/libgfortran/io/inquire.c @@ -47,7 +47,10 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit *u) generate_error (&iqp->common, LIBERROR_INQUIRE_INTERNAL_UNIT, NULL); if ((cf & IOPARM_INQUIRE_HAS_EXIST) != 0) - *iqp->exist = (u != NULL) || (iqp->common.unit >= 0); + *iqp->exist = (u != NULL && + iqp->common.unit != GFC_INTERNAL_UNIT && + iqp->common.unit != GFC_INTERNAL_UNIT4) + || (iqp->common.unit >= 0); if ((cf & IOPARM_INQUIRE_HAS_OPENED) != 0) *iqp->opened = (u != NULL); diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c index 4d7ca7abf7b..211dc349750 100644 --- a/libgfortran/io/transfer.c +++ b/libgfortran/io/transfer.c @@ -3985,6 +3985,19 @@ finalize_transfer (st_parameter_dt *dtp) next_record (dtp, 1); done: + + if (dtp->u.p.unit_is_internal) + { + fbuf_destroy (dtp->u.p.current_unit); + if (dtp->u.p.current_unit + && (dtp->u.p.current_unit->child_dtio == 0) + && dtp->u.p.current_unit->s) + { + sclose (dtp->u.p.current_unit->s); + dtp->u.p.current_unit->s = NULL; + } + } + #ifdef HAVE_USELOCALE if (dtp->u.p.old_locale != (locale_t) 0) { @@ -4094,8 +4107,6 @@ st_read_done (st_parameter_dt *dtp) { free (dtp->u.p.current_unit->filename); dtp->u.p.current_unit->filename = NULL; - free (dtp->u.p.current_unit->s); - dtp->u.p.current_unit->s = NULL; if (dtp->u.p.current_unit->ls) free (dtp->u.p.current_unit->ls); dtp->u.p.current_unit->ls = NULL; @@ -4165,8 +4176,6 @@ st_write_done (st_parameter_dt *dtp) { free (dtp->u.p.current_unit->filename); dtp->u.p.current_unit->filename = NULL; - free (dtp->u.p.current_unit->s); - dtp->u.p.current_unit->s = NULL; if (dtp->u.p.current_unit->ls) free (dtp->u.p.current_unit->ls); dtp->u.p.current_unit->ls = NULL; diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c index 66cd12dcdcd..2ca8525fbec 100644 --- a/libgfortran/io/unit.c +++ b/libgfortran/io/unit.c @@ -566,7 +566,11 @@ get_unit (st_parameter_dt *dtp, int do_create) is not allowed, such units must be created with OPEN(NEWUNIT=...). */ if (dtp->common.unit < 0) - return get_gfc_unit (dtp->common.unit, 0); + { + if (dtp->common.unit > NEWUNIT_START) /* Reserved units. */ + return NULL; + return get_gfc_unit (dtp->common.unit, 0); + } return get_gfc_unit (dtp->common.unit, do_create); } @@ -701,6 +705,9 @@ init_units (void) __gthread_mutex_unlock (&u->lock); } + /* The default internal units. */ + u = insert_unit (GFC_INTERNAL_UNIT); + u = insert_unit (GFC_INTERNAL_UNIT4); } diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index 61e9f7997b2..a07a3c9cea8 100644 --- a/libgfortran/io/unix.c +++ b/libgfortran/io/unix.c @@ -962,8 +962,8 @@ mem_flush (unix_stream *s __attribute__ ((unused))) static int mem_close (unix_stream *s) { - free (s); - + if (s) + free (s); return 0; }