[yast-devel] ruby2.7 issue with $LOAD_PATHS
Hi all, Most likely you already know about our crazy bug in the Tumbleweed installer that was reported some weeks ago [1]. Basically, the problem was raised because a same ruby file was "loaded" twice after requiring it for second time. Obviously this should not happen because Kernel#require method prevents that [2]. As the documentation states: "The absolute path of the loaded file is added to $LOADED_FEATURES. A file will not be loaded again if its path already appears in $LOADED_FEATURES". So, why is a file loaded twice in YaST? TL;DR: because ruby2.7 has a bug when requiring files from symlinks. In general, ruby expands the absolute path of a loaded file by following the symlink, so the $LOAD_FEATURES would contain the path of the real file instead of the symlink path. For example: # There is a symlink like # # /usr/share/foo --> /mnt/foo $LOAD_PATH.append("/usr/share/foo/lib") require "foobar" $LOADED_FEATURES.grep(/foobar/) # => "/mnt/foo/lib/foobar.rb" But there is a corner case in ruby2.7. Ruby tracks the file by using the symlink path when: * a new directory is added to the beginning of $LOAD_PATH and * any parent of the added directory is a symbolic link. # There is a symlink like # # /usr/share/foo --> /mnt/foo $LOAD_PATH.append("/usr/share/foo/lib") require "foobar" $LOADED_FEATURES.grep(/foobar/) # => "/mnt/foo/lib/foobar.rb" But: $LOAD_PATH.prepend("/usr/share/foo/lib") require "foobar" $LOADED_FEATURES.grep(/foobar/) # => "/usr/share/foo/lib/foobar.rb" Note the difference of the $LOADED_FEATURES when the path is added at the beginning of the list and at the end. And also note that this does not happen when the new added load path is a symlink itself: # There is a symlink like # # /usr/share/foo/lib --> /mnt/foo/lib $LOAD_PATH.append("/usr/share/foo/lib") require "foobar" $LOADED_FEATURES.grep(/foobar/) # => "/mnt/foo/lib/foobar.rb" And: $LOAD_PATH.prepend("/usr/share/foo/lib") require "foobar" $LOADED_FEATURES.grep(/foobar/) # => "/mnt/foo/lib/foobar.rb" All this is very unexpected, and only happens in ruby2.7. This weird behavior was making YaST to fail, see [3] for more details. I have prepared an script to automatically reproduce this issue (see the attached file). You can use it to see the difference with ruby2.7 and previous versions. Do you think this is actually a bug in ruby2.7? Or am I doing something wrong? Should we report a bug? For the time being, we have found a workaround to avoid the failure in YaST side. Regards, Iván [1] https://bugzilla.suse.com/show_bug.cgi?id=1172898 [2] https://apidock.com/ruby/Kernel/require [3] https://bugzilla.opensuse.org/show_bug.cgi?id=1172898#c20 -- José Iván López González YaST Team at SUSE LINUX GmbH IRC: jilopez
participants (1)
-
José Iván López González