From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=lersek@redhat.com; receiver=edk2-devel@lists.01.org Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 5E30C209574E1 for ; Tue, 27 Feb 2018 02:23:14 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B2FD14015170; Tue, 27 Feb 2018 10:29:19 +0000 (UTC) Received: from lacos-laptop-7.usersys.redhat.com (ovpn-120-21.rdu2.redhat.com [10.10.120.21]) by smtp.corp.redhat.com (Postfix) with ESMTP id B6BF61CBB3; Tue, 27 Feb 2018 10:29:18 +0000 (UTC) To: "Ni, Ruiyu" , Guo Heyi Cc: edk2-devel@lists.01.org, Star Zeng , Eric Dong References: <1519633779-130687-1-git-send-email-heyi.guo@linaro.org> <20180227004830.GA2261@SZX1000114654> From: Laszlo Ersek Message-ID: <169e8bb8-00c5-43ec-094a-28079a5fa1d1@redhat.com> Date: Tue, 27 Feb 2018 11:29:18 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 MIME-Version: 1.0 In-Reply-To: X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Tue, 27 Feb 2018 10:29:19 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Tue, 27 Feb 2018 10:29:19 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'lersek@redhat.com' RCPT:'' Subject: Re: [PATCH 1/1] MdeModulePkg/UefiBootManagerLib: limit recursive call depth X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 27 Feb 2018 10:23:14 -0000 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit On 02/27/18 06:48, Ni, Ruiyu wrote: > On 2/27/2018 8:48 AM, Guo Heyi wrote: >> Hi Laszlo, >> >> I agree the current patch makes the code ugly, and turning the logic >> into a >> normal loop should be the perfect solution. If Ray also agrees on it, >> I can try >> to do that. >> >> Thanks and regards, >> >> Heyi >> >> On Mon, Feb 26, 2018 at 05:23:29PM +0100, Laszlo Ersek wrote: >>> On 02/26/18 09:29, Heyi Guo wrote: >>>> Function BmRepairAllControllers may recursively call itself if some >>>> driver health protocol returns EfiDriverHealthStatusReconnectRequired. >>>> However, driver health protocol of some buggy third party driver may >>>> always return such status even after one and another reconnect. The >>>> endless iteration will cause stack overflow and then system exception, >>>> and it may be not easy to find that the exception is actually caused >>>> by stack overflow. >>>> >>>> So we limit the number of reconnect retry to 10 to improve code >>>> robustness. >>> >>> Not really my place to comment on this, but how about removing the >>> recursion entirely, and turning the logic into a normal (iterative) loop >>> instead? >>> >>> (1) Rename the current function to: >>> >>> STATIC >>> VOID >>> BmRepairAllControllersWorker ( >>>    OUT BOOLEAN *ReconnectRequired, >>>    OUT BOOLEAN *RebootRequired >>>    ); >>> >>> >>> (2) The worker function should end right before >>> >>>    if (ReconnectRequired) { >>>      BmRepairAllControllers (); >>>    } >>> >>> >>> (3) The worker function should not contain >>> >>>    RebootRequired    = FALSE; >>>    ReconnectRequired = FALSE; >>> >>> Such initialization should be left to the caller. >>> >>> >>> (4) The worker function should be called in a loop from a new >>> BmRepairAllControllers() function, like this: >>> >>>    Reconnect = 0; >>>    RebootRequired = FALSE; >>>    do { >>>      ReconnectRequired = FALSE; >>>      BmRepairAllControllersWorker (&ReconnectRequired, &RebootRequired); >>>      ++Reconnect; >>>    } while (ReconnectRequired && Reconnect < MAX_RECONNECT_REPAIR); >>> >>>    DEBUG_CODE (...); >>> >>>    if (RebootRequired) { >>>      ... >>>    } >>> >>> >>> In addition to eliminating the shoddy recursive call (and the shoddier >>> global counter, ewww :) ), this would fix the following other warts with >>> the code: >>> >>> - When a nested call chain is unwound, we currently dump a series of >>> "driver health info" lists (assuming no reboot is required), in the >>> DEBUG_CODE section. I would argue that we should do that only once, at >>> the end. (Even if we have to do it multiple times, it can be moved into >>> the worker function, to the end.) >>> >>> - It seems to be sufficient to accumulate RebootRequired into one >>> variable (i.e. not multiple instances of the same local variable on the >>> stack) and to act upon it at the very end. >>> >>> >>> Feel free to ignore my comments -- I just think we should be moving in >>> the opposite direction; that is, away from recursion (especially from >>> recursion combined with global variables -- that's one difficult pattern >>> to reason about). > > How about to just remove the global variable? > I prefer to change BmRepairAllControllers in the following prototype: > VOID > BmRepairAllControllers ( >   UINTN  ReconnectRepairCount >   ); > And start to call this like BmRepairAllControllers (0). > > I am neutral between recursive call and while loop. > But I am afraid such a big change may introduce some bugs. > And I also like to move the DEBUG_CODE to before: > if (ReconnectRequired) { >   BmRepairAllControllers (ReconnectRepairCount + 1); > } > So that we can dump the health info for every reconnect repair. Sure, that too works for me. Thanks! Laszlo