https://bugs.kde.org/show_bug.cgi?id=525989

            Bug ID: 525989
           Summary: Application order for a MIME type is not deterministic
                    when offers tie on preference
    Classification: Frameworks and Libraries
           Product: frameworks-kservice
      Version First 6.26.0
       Reported In:
          Platform: Other
                OS: Linux
            Status: REPORTED
          Severity: normal
          Priority: NOR
         Component: general
          Assignee: [email protected]
          Reporter: [email protected]
                CC: [email protected]
  Target Milestone: ---

The order KApplicationTrader returns for a MIME type, and therefore the default
application, changes between runs of kbuildsycoca6 on an unchanged system.
Installing any package rebuilds ksycoca, so a user's default application for a
type can silently change after an unrelated package install.

STEPS TO REPRODUCE

1. Install two desktop files claiming the same type, with no mimeapps.list
entry for it:

/usr/share/applications/tiebreak-alpha.desktop
[Desktop Entry]
Type=Application
Name=Tiebreak alpha
Exec=/bin/true %u
MimeType=x-scheme-handler/tiebreaktest;

/usr/share/applications/tiebreak-beta.desktop   (same, Name=Tiebreak beta)

2. kbuildsycoca6 --noincremental
3. KApplicationTrader::preferredService("x-scheme-handler/tiebreaktest")
4. Repeat fromĀ 2.

OBSERVED RESULT

The winner alternates. 12 runs: 8 tiebreak-alpha, 4 tiebreak-beta. With
QT_HASH_SEED=0 it is stable across runs.

Same thing with real applications where calibre and libreoffice both claim
application/vnd.openxmlformats-officedocument.wordprocessingml.document. 20
runs: 9 libreoffice-writer, 6 calibre-gui, 3 calibre-ebook-edit, 2
calibre-ebook-viewer.

EXPECTED RESULT

Same input, same order.

CAUSE

KBuildServiceFactory::populateServiceTypes() iterates m_entryDict
(KSycocaEntryDict is a QHash) and appends one offer per service, all with
preference 1. KServiceOffer::operator< compares only mimeTypeInheritanceLevel
and then preference. saveOfferList() sorts with std::stable_sort, so offers
that tie on both keep their insertion order, which is QHash iteration order,
randomized per process by Qt.

Any type whose top candidates are not separated by a mimeapps.list entry is
decided by the hash seed.

SUGGESTED FIX

Add a deterministic last-resort key to KServiceOffer::operator<, for instance
KService::storageId(), the way 7e643dbc did it for KServiceGroup.

Checked master: operator<, the stable_sort and the m_entryDict iteration are
unchanged. 9e9f4de6 fixed a related order dependence in
KOfferHash::addServiceOffer, but not this one.

SOFTWARE/OS VERSIONS

kservice 6.28.0 and 6.26.0, Plasma 6.6.5, Qt 6, ALT Linux x86_64.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to