Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get Information about Shared Libs and Plug-ins and Missing UI Extension Handling #1194

Merged
merged 20 commits into from Sep 15, 2021

Conversation

shundhammer
Copy link
Contributor

@shundhammer shundhammer commented Sep 7, 2021

Trello

https://trello.com/c/gT8nMq7O/2635-3-featureshouldhave-handle-more-gracefully-when-libyui-libraries-are-missing

Jira

Problem

When a user installed the system with "no recommends", i.e. recommended packages were not installed, the resulting system will also not have the Qt-Pkg (YQPackageSelector) plug-in because the libyui-qt-pkg package is not required unconditionally.

So when the user starts the YaST control center in the graphical (Qt) version and wants to start the YaST package management module from there, this will fail with a very obscure error message telling the user that "UI plug-in qt-pkg could not be loaded".

Desired Outcome

Give the user a much better message so there is a realistic chance to fix the problem.

Minimum: Give a hint that the package needed for that action was not installed, of course including what package that was.

Better: Open a pop-up dialog explaining the situation and offering to try to install that package directly from there, and give a hint to the alternative: Start the package management module in the NCurses version.

Infrastructure for the Solution

This PR adds a class SharedLibInfo to query the system what shared libs were loaded in the running process, and a more specialized subclass UIPluginInfo that gives more specific information about UI plug-ins among those loaded shared libs.

The SharedLibInfo base class uses the (very handy) /proc/self/maps file to collect that information. That file contains information about all memory-mapped objects which includes all shared libs and all dlopen()'ed files (which includes our UI plug-ins).

Sample /proc/self/maps:

https://github.com/yast/yast-yast2/blob/huha-plugins/library/system/test/data/proc-maps/proc-maps-qt

UI Plug-Ins

UIPluginInfo uses that to find shared libs that follow the directory and naming convention for libyui plug-ins, i.e. all shared libs in a subdirectory yui/ somewhere that start with the libyui- prefix. The one with the shortest base name among them is considered the UI main plug-in, regardless of what UI is currently being used; this does not limit the strategy to the well-known Qt and NCurses UIs, but leaves room for further development.

In practice, a YaST process running the Qt UI might have those loaded:

  • libyui-qt (always if the Qt UI is used)

  • libyui-qt-pkg (optional)

  • libyui-qt-graph (optional)

  • libyui-rest-api (optional; only in the SUSE openQA environment)

  • libyui-qt-rest-api (optional; only in the SUSE openQA environment)

with the NCurses UI, it might be those instead:

  • libyui-ncurses (always if the NCurses UI is used)

  • libyui-ncurses-pkg (optional)

  • libyui-rest-api (optional; only in the SUSE openQA environment)

  • libyui-qt-rest-api (optional; only in the SUSE openQA environment)

In practice, when this class is used to check if a UI extension like "-pkg" or "-graph" is available, there will only be one of them, libyui-qt or libyui-ncurses.

The UiPluginsInfo class also provides some methods to build a full path for a UI extension that may or may not be available, based on the currently used UI main plugin's path and SO number; and also for the name of the package that should (per our conventions) include that extension.

UI Developer Support

This can (and should) be used to check if the plug-in is actually there, and if it's there in the right directory and with the right libyui SO number: In the directory from where the UI will attempt to load the extension.

That means that it even covers cases where a developer needs to bump the libyui SO version, yet (since that part is still under development) there is no package available yet: If everything is done correctly, it will check for a plug-in libyui-qt-pkg.so.42.0.0 from a development plug-in directory /work/devel/lib/yui if the UI was loaded from /work/devel/lib/yui/libyui-qt.so.42.0.0, and if that actually exists, it will not insist to install a nonexistent package libyui-qt-pkg42 which would very much block that developer's work.

Caveat

Those classes are not meant for UI layout micro-tweaking. Do not use them to check if the UI is running in graphical or in text mode and then use a different layout or different margins; that would pretty much defeat the purpose of having a back-end-transparent UI engine. Use UI capabilities instead (see the UI reference documentation) if needed.

If you find they are not granular enough, please let's discuss that and add new capabilities instead; or, better yet, let's find a way to avoid the need to get down to that level of UI implementation detail.

Using the Infrastructure: Handling Missing UI Extension Plug-Ins

Since we need this in several YaST modules, making use of this infrastructure went to this same package, so all that we need in the YaST application parts are now 3 lines of code:

  require "ui/ui_extension_checker"
  ...
  ...
  ui_extension_checker = UIExtensionChecker.new("pkg")
  return unless ui_extension_checker.ok?

  # Run the package selection

This will take care of the rest:

  • It checks if the binary plug-in for the UI extension is available for loading (via dlopen()) from the same directory as the UI main plug-in (Qt, NCurses, ...)
  • If it is not, it opens a pop-up dialog asking if the user wishes to install the corresponding package
  • If the user confirms that, the package is installed, and the package selection starts (no program restart necessary)
  • If the user declines installing the package, the module exits (usually; it's up to the module how to handle this)

Notice that it doesn't matter at all if the package was previously installed or not; this works even if you messed up your system manually.

Screenshots

need-pkg-installed-qt

need-pkg-installed-ncurses

Related PRs

@coveralls
Copy link

coveralls commented Sep 7, 2021

Coverage Status

Coverage increased (+0.3%) to 41.218% when pulling 9f22487 on huha-plugins into 8f7e709 on master.

Copy link
Member

@lslezak lslezak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some nitpicking, it looks good! 👍

library/system/src/lib/yast2/ui_plugin_info.rb Outdated Show resolved Hide resolved
library/system/test/shared_lib_info_test.rb Show resolved Hide resolved
@shundhammer shundhammer changed the title Get Information about Shared Libs and Plug-ins Get Information about Shared Libs and Plug-ins and Missing UI Extension Handling Sep 15, 2021
@shundhammer shundhammer marked this pull request as ready for review September 15, 2021 12:51
Copy link
Member

@lslezak lslezak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@shundhammer shundhammer merged commit 2e561ac into master Sep 15, 2021
@shundhammer shundhammer deleted the huha-plugins branch September 15, 2021 17:00
@yast-bot
Copy link
Contributor

✔️ Public Jenkins job #325 successfully finished
✔️ Created OBS submit request #919267

@yast-bot
Copy link
Contributor

✔️ Internal Jenkins job #163 successfully finished
✔️ Created IBS submit request #252142

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants