Bug #90648

Infinite recursion with new mount point support in sites with multiple websites with same slug name for mount points

Added by Christian Eßl over 1 year ago. Updated over 1 year ago.

Status:
New
Priority:
Should have
Assignee:
-
Category:
Link Handling, Site Handling & Routing
Target version:
-
Start date:
2020-03-05
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
9
PHP Version:
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

We have a multidomain website that is structured like:

  • Website A
    • mounted-subpage (Original)
  • Website B
    • mounted-subpage (Mount of the page in Website A)
  • Website C (hidden)
    • mounted-subpage (Mount of the page in Website A)

Basically every website has the subpage "mounted-subpage" with identical slugs. Website A has the original page, all the other websites use a mountpoint set to this page.
Now when I open the subpage in the frontend from Website A like:

https://website-a.com/mounted-subpage

we seem to get an infinite recursion here. (Nginx just logs an "Allowed memory size exhausted" here).
This happens in SiteFinder::getSiteByPageId() in the last line:

/**
     * Traverses the rootline of a page up until a Site was found.
     *
     * @param int $pageId
     * @param array $rootLine
     * @param string|null $mountPointParameter
     * @return Site
     * @throws SiteNotFoundException
     */
    public function getSiteByPageId(int $pageId, array $rootLine = null, string $mountPointParameter = null): Site
    {
        if ($pageId === 0) {
            // page uid 0 has no root line. We don't need to ask the root line resolver to know that.
            $rootLine = [];
        }
        if (!is_array($rootLine)) {
            try {
                $rootLine = GeneralUtility::makeInstance(RootlineUtility::class, $pageId, $mountPointParameter)->get();
            } catch (PageNotFoundException $e) {
                // Usually when a page was hidden or disconnected
                // This could be improved by handing in a Context object and decide whether hidden pages
                // Should be linkeable too
                $rootLine = [];
            }
        }
        foreach ($rootLine as $pageInRootLine) {
            if (isset($this->mappingRootPageIdToIdentifier[(int)$pageInRootLine['uid']])) {
                return $this->sites[$this->mappingRootPageIdToIdentifier[(int)$pageInRootLine['uid']]];
            }
        }
        throw new SiteNotFoundException('No site found in root line of page ' . $pageId, 1521716622);
    }

The SiteNotFoundException is thrown, when we get the error about the memory exhaustion (what exactly happens recursion-wise, I can't say yet).

  • Now look at the example page tree above. When I debugged the problem, I found out, that one of our websites root page was hidden. (Website C is not in use). But according to the stacktrace, the PageRouter inside matchRequest() looks up possible candidates in getPagesFromDatabaseForCandidates().
  • In there happens the new mount point magic. The function now returns our possible candidates for the slug "mounted-subpage", including the one of the hidden Website C.
  • Later, SiteFinder::getSiteByPageId() tries to find the site for this page, but fails doing so (Expected, the website is hidden) and throws a SiteNotFoundException.
  • SiteMatcher::matchByPageId catches the exception and falls back to "$this->pseudoSiteFinder->getSiteByPageId()). It successfully returns a PseudoSite for our hidden Website C;
  • Later in PageRouter::getPagesFromDatabaseForCandidates(), if $mountPageInformation is set (yes in this case), the recursion happens when $this->findPageCandidatesOfMountPoint() is called. Why it ends up in an infinite recursion I am not really sure yet. From what I see it constantly juggles between the mountpoints of Website B and Website C. (Which both point to the original page in Website A)

Related issues

Related to TYPO3 Core - Bug #86331: Mountpoints not working with new site configurationsClosed2018-09-20

Actions
Related to TYPO3 Core - Bug #90469: Mountpoint information fetched for slug outside of site rootClosedPatrick Broens2020-02-21

Actions
#1

Updated by Christian Eßl over 1 year ago

  • Description updated (diff)
#2

Updated by Christian Eßl over 1 year ago

  • Related to Bug #86331: Mountpoints not working with new site configurations added
#3

Updated by Christian Eßl over 1 year ago

* Unhiding Website C does not resolve the problem. Perhaps it is because the website does not have a Site configuration and falls back to a PseudoSite?

#4

Updated by Christian Eßl over 1 year ago

Ok, I think I got it:

  • getPagesFromDatabaseForCandidates() always takes $excludeUids as last parameter, which contains all page ids that should not be looked up.
  • The call findPageCandidatesOfMountPoint() in that function does not remember these exluded uids.
  • Because we have 3+ page trees that have all the same mounted page with the same slug name, it keeps juggling around between two of them, because it fails to remember the page uids it already looked up.
#5

Updated by Christian Eßl over 1 year ago

  • Related to Bug #90469: Mountpoint information fetched for slug outside of site root added
#6

Updated by Christian Eßl over 1 year ago

The patch for #90469 solves the problem. (Just needs a little bit of extra work)

#7

Updated by Christian Eßl over 1 year ago

  • Subject changed from Infinite recursion with new mount point support in sites when having a hidden website to Infinite recursion with new mount point support in sites with multiple websites with same slug name for mount points

Also available in: Atom PDF