Bug 1218064 - YaST2 and Ruby 3.3
Summary: YaST2 and Ruby 3.3
Status: RESOLVED FIXED
Alias: None
Product: openSUSE Tumbleweed
Classification: openSUSE
Component: YaST2 (show other bugs)
Version: Current
Hardware: Other Other
: P5 - None : Normal (vote)
Target Milestone: ---
Assignee: Josef Reidinger
QA Contact: Jiri Srain
URL: https://trello.com/c/E0NU47vG/3514-ad...
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-12-14 14:07 UTC by Ana Guerrero
Modified: 2024-01-17 16:34 UTC (History)
2 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
strace from failed case (1.73 MB, text/plain)
2023-12-27 16:25 UTC, Josef Reidinger
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Ana Guerrero 2023-12-14 14:07:54 UTC
yast2 and ruby2.3

ruby2.3 is currently staged for Factory with the idea of becoming the new default ruby version. Around 25 yast2 packages are failing to build:

autoyast2
yast2-add-on
yast2-alternatives
yast2-caasp
yast2-configuration-management
yast2-country
yast2-fcoe-client
yast2-firewall
yast2-ftp-server
yast2-installation
yast2-iscsi-client
yast2-kdump
yast2-nfs-client
yast2-nfs-server
yast2-online-update
yast2-proxy
yast2-rdp
yast2-registration
yast2-samba-server
yast2-security
yast2-services-manager
yast2-slp
yast2-sysconfig
yast2-users
yast2-widget-demo

You can take a look to the logs at https://build.opensuse.org/project/monitor/openSUSE:Factory:Staging:I?arch_x86_64=1&defaults=0&failed=1&repo_standard=1
Please note this url can change and disappear but should be available for a few days at least.
Comment 1 Stefan Hundhammer 2023-12-14 14:18:39 UTC
Ruby 2.3? That would be a flashback to late 2015...

I guess you mean Ruby 3.3, right?
Comment 3 Stefan Hundhammer 2023-12-14 14:36:39 UTC

yast2-installation, yast2-country:

Lots of this error:

> RuntimeError:
>   Failed to load Module 'AddOnProduct' due to: cannot load such file -- cheetah
> # /usr/share/YaST2/lib/yast2/execute.rb:24:in `<top (required)>'
> # /usr/share/YaST2/lib/y2packager/package.rb:14:in `<top (required)>'
> # /usr/share/YaST2/lib/y2packager/release_notes_fetchers/rpm.rb:15:in `<top (required)>'
> # /usr/share/YaST2/lib/y2packager/release_notes_reader.rb:15:in `<top (required)>'
> # /usr/share/YaST2/lib/y2packager/product.rb:15:in `<top (required)>'



yast2-widget-demo:

I see a lot of:

> LoadError:
>   cannot load such file -- abstract_method
> # ./src/lib/widget_demo/pages/base.rb:20:in `<top (required)>'
> # ./src/lib/widget_demo/page_navigator.rb:20:in `<top (required)>'
> # ./src/lib/widget_demo/dialog.rb:20:in `<top (required)>'
> # ./test/dialog_smoke_test.rb:22:in `<top (required)>'
Comment 4 Ana Guerrero 2023-12-14 14:56:28 UTC
Yep, Ruby 3.3. Thank you for taking care Stefan.
Comment 5 Josef Reidinger 2023-12-20 10:56:48 UTC
it looks like it still use some ruby3.2 packages during build which is wrong [    

7s] ruby3.2-rubygem-nokogiri-1.15.5-3.8   ########################################
[    7s] update-alternatives: using /usr/bin/nokogiri.ruby3.2-1.15.5 to provide /usr/bin/nokogiri (nokogiri) in auto mode
Comment 6 Josef Reidinger 2023-12-20 11:01:39 UTC
root of issue why it does not provide version 3.3 is this one:

nothing provides ruby3.3-without-jemalloc >= 3.3.0 needed by ruby3.3-rubygem-nokogiri, (got version 3.3.0~rc1-1.2 provided by ruby3.3)
Comment 7 Josef Reidinger 2023-12-27 12:05:26 UTC
good, now ruby3.3 is in place and we have some nice funny failures in test suite like this in yast2:

[   16s]   1) #<Yast::HooksClass:0x00007f374eb9b388> tracks the results of the run hook files
[   16s]      Failure/Error: expect(succeeded_hook_file.result.exit).to eq(0)
[   16s] 
[   16s]        expected: 0
[   16s]             got: 134
[   16s] 
[   16s]        (compared using ==)
[   16s]      # ./library/general/test/hooks_test.rb:63:in `block (2 levels) in <module:Yast>'
[   16s] 
[   16s]   2) #<Yast::GPGClass:0x00007f374c06cf68> #decrypt_symmetric file contain gpg encrypted file returns content if password was correct
[   16s]      Failure/Error: expect(described_class.decrypt_symmetric(@path, "test")).to match(/<zeroOrMore>/)
[   16s] 
[   16s]      Yast::GPGFailed:
[   16s]        gpg: directory '/home/abuild/.gnupg' created
[   16s]        gpg: AES256.CFB encrypted data
[   16s]        gpg: encrypted with 1 passphrase
[   16s]        [ASYNC BUG] rb_thread_wakeup_timer_thread: write(3)
[   16s]        EBADF
[   16s] 
[   16s]        ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux-gnu]
[   16s]      # ./library/gpg/src/modules/GPG.rb:412:in `decrypt_symmetric'
[   16s]      # ./library/gpg/test/gpg_test.rb:50:in `block (4 levels) in <top (required)>'
[   16s]      # ./library/gpg/test/gpg_test.rb:42:in `block (2 levels) in <top (required)>'
[   16s] 
[   16s]   3) #<Yast::GPGClass:0x00007f374c06cf68> #encrypted_symmetric will create output file that is encrypted
[   16s]      Failure/Error: described_class.encrypt_symmetric(@path, path, "test")
[   16s] 
[   16s]      Yast::GPGFailed:
[   16s]        [ASYNC BUG] rb_thread_wakeup_timer_thread: write(3)
[   16s]        EBADF
[   16s] 
[   16s]        ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux-gnu]
[   16s]      # ./library/gpg/src/modules/GPG.rb:433:in `encrypt_symmetric'
[   16s]      # ./library/gpg/test/gpg_test.rb:89:in `block (4 levels) in <top (required)>'
[   16s]      # ./library/gpg/test/gpg_test.rb:87:in `block (3 levels) in <top (required)>'
[   16s]      # ./library/gpg/test/gpg_test.rb:42:in `block (2 levels) in <top (required)>'


I will wait till build settle a bit and then try to debug what this async bug means
Comment 8 Josef Reidinger 2023-12-27 15:48:58 UTC
After checking, I can say that other yast modules failed due to this one as it use old one with ruby 3.2 dependencies. So I need to check why calling external call cause this crash. I suspect some new async improvements and try to search if there are way to disable it for some calls
Comment 9 Josef Reidinger 2023-12-27 16:05:47 UTC
OK, so good news is that I can reproduce it...and I debug that also hooks failure is caused by that EBADF error:

2023-12-27 16:04:16 <3> localhost.localdomain(12778) [bash] ShellCommand.cc(shellcommand):78 [ASYNC BUG] rb_thread_wakeup_timer_thread: write(3)
2023-12-27 16:04:16 <3> localhost.localdomain(12778) [bash] ShellCommand.cc(shellcommand):78 EBADF

I am just not sure what currently cause it
Comment 10 Josef Reidinger 2023-12-27 16:25:10 UTC
Created attachment 871572 [details]
strace from failed case

I extract strace from single failed case. I see bunch of EBADF which is expected ( to close unnecessary fds ), but then it tries to write to 3 with failure, and later it passed.

snippet:

[pid 13003] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=13004, si_uid=399, si_status=0, si_utime=6 /* 0.06 s */, si_stime=3 /* 0.03 s */} ---
[pid 13003] write(3, "\1\0\0\0\0\0\0\0", 8) = -1 EBADF (Bad file descriptor)
[pid 13003] write(2, "[ASYNC BUG] ", 12) = 12
[pid 13003] write(2, "rb_thread_wakeup_timer_thread: w"..., 39 <unfinished ...>
[pid 12996] <... read resumed>"[ASYNC BUG] ", 4096) = 12

but different pid write same sequence correctly
[pid 13002] write(3, "\1\0\0\0\0\0\0\0", 8) = 8

and I also failed to find in strace that pid 13003 even open something with fd 3
Comment 11 Josef Reidinger 2023-12-27 16:30:44 UTC
OK, so something is definitively wrong in way how we call SCR and bash in it. as it failed always with it and works with cheetah.

minimal reproducible case where first cheetah code works and second SCR call failed. Sadly replace all SCR calls is not even middle term solution



require "cheetah"

puts Cheetah.run("echo", "test", stdout: :capture)

require "yast"

puts Yast::SCR.Execute(Yast::Path.new(".target.bash_output"), "echo test")
Comment 12 Josef Reidinger 2023-12-27 20:55:08 UTC
another test script that shows that affected is also .target.bash

require "yast"

puts Yast::SCR.Execute(Yast::Path.new(".target.bash"), "echo test")
puts Yast::SCR.Execute(Yast::Path.new(".target.bash_output"), "echo test")
Comment 13 Josef Reidinger 2023-12-27 21:18:21 UTC
btw message is from this part of ruby. Still I think that yast core is not ready for any fancy threading or running in multiple processes

https://github.com/ruby/ruby/blob/ruby_3_3/error.c#L1096

so I need to check how it can happen that ruby try to do something async.
Comment 14 Josef Reidinger 2023-12-27 21:44:06 UTC
so I think it is raised at https://github.com/ruby/ruby/blob/ruby_3_3/thread_pthread.c#L3033
but I am not sure what cause that wrong fd. If something close it or ruby does not open it?
Comment 15 Martin Vidner 2024-01-08 09:58:54 UTC
(In reply to Josef Reidinger from comment #10)
> Created attachment 871572 [details]
> strace from failed case
> 
> I extract strace from single failed case. I see bunch of EBADF which is
> expected ( to close unnecessary fds ), but then it tries to write to 3 with
> failure, and later it passed.

Yes. There's a loop where we close unneccessary FDs:
[pid 12999] close(1023)                 = -1 EBADF (Bad file descriptor)
...
[pid 12999] close(7)                    = -1 EBADF (Bad file descriptor)
[pid 12999] close(6)                    = 0
[pid 12999] close(5)                    = 0
[pid 12999] close(4)                    = 0
[pid 12999] close(3)                    = 0

but the bug is that unknown to us, FD 3 is actually needed to stay open.


> but different pid write same sequence correctly
> [pid 13002] write(3, "\1\0\0\0\0\0\0\0", 8) = 8

That's a later process which did not hit our bug

> and I also failed to find in strace that pid 13003 even open something with
> fd 3

The syscall is eventfd2, https://www.man7.org/linux/man-pages/man2/eventfd.2.html
found by
  grep =.3$ strace.out | grep -v open
Comment 16 Martin Vidner 2024-01-17 16:34:35 UTC
Fixed this problem:

Don't close file descriptors in .target.bash calls (bsc#1218064)
avoiding "[ASYNC BUG] rb_thread_wakeup_timer_thread: write(3) EBADF"
with Ruby 3.3

RPM: yast2-core-5.0.2
Git: https://github.com/yast/yast-core/pull/166
OBS SR: https://build.opensuse.org/request/show/1137997

and there are no more yast related build failures left in Staging:I