On 13/05/2024 10.28, Rasmus Villemoes wrote:
> On 07/05/2024 19.23, Tom Rini wrote:
>> On Tue, May 07, 2024 at 09:17:46AM +0200, Yoann Congal wrote:
>>> Le 06/05/2024 à 19:43, Tom Rini a écrit :
>>>> On Sun, May 05, 2024 at 03:53:53PM +0200, Yoann Congal wrote:
>>>>
>>>>> From: Masahiro Yamada <masahi...@kernel.org>
>>>>>
>>>>> This is a cherry-pick from the kernel commit:
>>>>> 6262afa10ef7c (kconfig: default to zero if int/hex symbol lacks default 
>>>>> property, 2023-11-26)
>>>>>
>>>>> When a default property is missing in an int or hex symbol, it defaults
>>>>> to an empty string, which is not a valid symbol value.
>>>>>
>>>>> It results in an incorrect .config, and can also lead to an infinite
>>>>> loop in scripting.
>>>>>
>>>>> Use "0" for int and "0x0" for hex as a default value.
>>>>>
>>>>> Signed-off-by: Masahiro Yamada <masahi...@kernel.org>
>>>>> Reviewed-by: Yoann Congal <yoann.con...@smile.fr>
>>>>>
>>>>> Signed-off-by: Yoann Congal <yoann.con...@smile.fr>
>>>>> ---
>>>>> Added context that was not in the upstream commit:
>>>>> The infinite loop case happens with a configuration defined like this
>>>>> (a hex config without a valid default value):
>>>>>   config HEX_TEST
>>>>>           hex "Hex config without default"
>>>>>
>>>>> And using:
>>>>>   $ make oldconfig < /dev/null
>>>>>   scripts/kconfig/conf  --oldconfig Kconfig
>>>>>   *
>>>>>   * General setup
>>>>>   *
>>>>>
>>>>>   Error in reading or end of file.
>>>>>
>>>>>   Error in reading or end of file.
>>>>>   Hex config without default (HEX_TEST) [] (NEW)
>>>>>
>>>>>   Error in reading or end of file.
>>>>>   Hex config without default (HEX_TEST) [] (NEW)
>>>>>   # This loops forever
>>>>>
>>>>> NB: Scripted config manipulation often call make with /dev/null as
>>>>> stdin (Yocto recipe, CI build, ...)
>>>>>
>>>>> This was discovered when working on Yocto bug:
>>>>> https://bugzilla.yoctoproject.org/show_bug.cgi?id=14136
>>>
>>> Hi Tom,
>>>
>>>> I'm surprised this was accepted. In the past I've wanted to avoid this
>>>> kind of change in Kconfig because while the empty string can be easily
>>>> be checked in the code as "user didn't really configure this, do
>>>> nothing" a value of zero is a valid option in these cases and so then in
>>>> the code we need a bool symbol to decide if the hex/int symbol is set or
>>>> not.
>>>
>>> For context (and what it's worth), before this patch was merged, I've tried 
>>> to fix this problem with a patch of my own which only exited the config 
>>> process when the infinite loop would start:
>>> "[PATCH v4] kconfig: avoid an infinite loop in oldconfig/syncconfig" [0]
>>> ... the v5 version was a bit more severe and exited as soon as an error was 
>>> hit, it was then removed from -next because it triggered a build failure 
>>> [1].
>>>
>>>> Today this is less of an issue than it used to be in U-Boot with
>>>> everything CONFIG-related migrated to Kconfig and so there's no longer
>>>> the question of if we missed migrating a file that defined the value but
>>>> there's still places we have in the code where hex symbol is undefined
>>>> is not the same thing as hex symbol is 0x0.
>>>>
>>>> Is there a specific use case you have for this in U-Boot? It's been a
>>>> while, but it's also been cases of newly introduced symbols in Kconfig
>>>> files with incorrect dependencies, where the infinite loop in kconfig
>>>> happened, CI failed and we caught the problem.
>>>
>>> For a specific example, one can trigger this with CMD_PSTORE_MEM_ADDR like 
>>> this (tested on today's master):
>>>   make qemu_arm64_defconfig
>>>   make menuconfig
>>>    # activate CONFIG_CMD_PSTORE=y but forget to fill CMD_PSTORE_MEM_ADDR
>>>   make < /dev/null # This emulates a Yocto/scripted/CI build and loops 
>>> infinitely
>>>
>>> But, my more general use case is the Yocto dev trying to change the U-Boot 
>>> (or any kconfig based software) config and accidentally trigger this.
>>> In Yocto, what they will see is a do_configure task taking a very long time 
>>> but they won't see the looping logs the detect the problem (This is caught 
>>> later by filing the RAM and the build process is killed by OOM, or the disk 
>>> run out of space filed multi-GB log files).
>>>
>>> I'm sadly aware that defining a default value for this kind of config 
>>> (fixed addresses) is not really sensible but the build time infinite loop 
>>> is not good either.
>>
>> Exactly, but to me it's worse to cover up the build issue and introduce
>> a runtime issue instead. Something builds but then crashes at run time
>> is worse to me than builds fail / get stuck. Using your example,
>> CMD_PSTORE_MEM_ADDR depends on CMD_PSTORE and so if someone enables
>> CMD_PSTORE in a config fragment but doesn't define the address, the
>> build should not complete. Using 0x0 means that oops, now it fails to
>> work and might not be obvious why either.
> 
> I agree with Tom. Yes, we've also hit those yocto failures with a
> multi-GB do_configure log file, and that's pretty annoying when one just
> starts a build cooking over night and then the next day one's laptop has
> a filled disk. So clearly there is/was a problem to solve.
> 
> However, blindly adding a "default default" of 0 is not the right thing
> to do. It seems much better that, when there's no configured default and
> kconfig gets EOF when asking the user for input (as in the 'make
> oldconfig < /dev/null' case), kconfig should exit with an error
> explicitly saying "no value given for CONFIG_XYZ which also doesn't have
> a default value". That stops the build, and leaves precisely an
> indication what the problem is. 

For my own curiosity I tried to find where the infinite loop is, and I
think it's the while(1) in conf_string(). Not tested at all, but perhaps
something like

diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 965bb40c50e5..604b55124318 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -355,8 +355,7 @@ static int conf_string(struct menu *menu)
                printf("%*s%s ", indent - 1, "", menu->prompt->text);
                printf("(%s) ", sym->name);
                def = sym_get_string_value(sym);
-               if (def)
-                       printf("[%s] ", def);
+               printf("[%s] ", def ?: "no default");
                if (!conf_askvalue(sym, def))
                        return 0;
                switch (line[0]) {
@@ -376,6 +375,11 @@ static int conf_string(struct menu *menu)
                }
                if (def && sym_set_string_value(sym, def))
                        return 0;
+               if (!def) {
+                       fprintf(stderr, "A value for %s must be
provided\n", sym->name);
+                       if (feof(stdin))
+                               exit(1);
+               }
        }
 }


would be an improvement. There really is no point in looping forever
when there's nothing more to get from stdin.

Rasmus

Reply via email to