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

nextpnr-ecp5 GUI locks up generating tooltip for downhill pips #1368

Open
danderson opened this issue Sep 14, 2024 · 1 comment
Open

nextpnr-ecp5 GUI locks up generating tooltip for downhill pips #1368

danderson opened this issue Sep 14, 2024 · 1 comment

Comments

@danderson
Copy link

I seem to have found an infinite loop in the GUI code, or at least pathological slowness that fails to un-freeze the GUI after 30 minutes at 100% CPU. This does not require a loaded design.

To reproduce:

  • Get nextpnr 0.7. Specifically, I'm using the nixpkgs-unstable build, which is built at the nextpnr-0.7 tag with a single change irrelevant to this issue (optionally switches out python interpreters in the ice40 variant).
  • Start the GUI: nextpnr-ecp5 --gui
  • Take care to avoid mousing over the properties panel (highlighted below) for now

image

  • In the elements list, select the "Wires" tab, then expand X0/Y0 and select the first wire within (X0/Y0/G_JLECLK1)
  • Mouse over the first few elements in the properties panel ("Name", "Type"), observe normal behavior.
  • Mouse over the entries under "Pips Downhill" or "Pips Uphill". Observe tooltip doesn't render, and GUI locks up.
  • In top or similar tool, observe nextpnr-ecp5 pegging one core at 100%. I gave it 30min on a 5950X to unstick itself, without success.

image

Here is perf data while the GUI is spinning, recording full stack traces for 60s. Take care, the 1.6MiB gz decompresses to ~50MiB.

perf.data.gz

perf report says the GUI is spending 99% of runtime in this stack trace, with 40% of that being in QList<nextpnr_ecp5::TreeModel::Item*>::removeAll:

-   40.27%    40.22%  .nextpnr-ecp5-w  .nextpnr-ecp5-wrapped           [.] QList<nextpnr_ecp5::TreeModel::Item*>::removeAll(nextpnr_ecp5::TreeModel::Item* const&) [clone .isra.0]
     40.22% _start
        __libc_start_main@@GLIBC_2.34
        __libc_start_call_main
        main
        nextpnr_ecp5::CommandHandler::exec()
        nextpnr_ecp5::CommandHandler::executeMain(std::unique_ptr<nextpnr_ecp5::Context, std::default_delete<nextpnr_ecp5::Context> >)
        QCoreApplication::exec()
        QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)
        QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)
        g_main_context_iteration
        g_main_context_iterate_unlocked.isra.0
        g_main_dispatch
        userEventSourceDispatch(_GSource*, int (*)(void*), void*)
        QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>)
        QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*)
        QCoreApplication::notifyInternal2(QObject*, QEvent*)
        nextpnr_ecp5::Application::notify(QObject*, QEvent*)
        QApplicationPrivate::notify_helper(QObject*, QEvent*)
        QWidgetWindow::event(QEvent*)
        QWidgetWindow::handleMouseEvent(QMouseEvent*)
        QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool)
        QCoreApplication::notifyInternal2(QObject*, QEvent*)
        nextpnr_ecp5::Application::notify(QObject*, QEvent*)
        QApplication::notify(QObject*, QEvent*)
        QApplicationPrivate::notify_helper(QObject*, QEvent*)
        QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*)
        QFrame::event(QEvent*)
        QWidget::event(QEvent*)
        QtPropertyEditorView::mouseMoveEvent(QMouseEvent*)
        void doActivate<false>(QObject*, int, void**)
        QtTreePropertyBrowser::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)
        void doActivate<false>(QObject*, int, void**)
        nextpnr_ecp5::DesignWidget::onHoverPropertyChanged(QtBrowserItem*)
        nextpnr_ecp5::TreeModel::Model::nodeForId(nextpnr_ecp5::IdStringList) const
        nextpnr_ecp5::TreeModel::ElementXYRoot<nextpnr_ecp5::PipId>::getById(nextpnr_ecp5::IdStringList)
        nextpnr_ecp5::TreeModel::ElementList<nextpnr_ecp5::PipId>::fetchMore(int)
        nextpnr_ecp5::TreeModel::IdStringItem::~IdStringItem()
        QList<nextpnr_ecp5::TreeModel::Item*>::removeAll(nextpnr_ecp5::TreeModel::Item* const&) [clone .isra.0]

I looked through the commit history since 0.7 was tagged, and don't see an obvious commit that would have fixed this. I'll try to build from HEAD and check that it reproduces there.

@danderson
Copy link
Author

Reproduces the same on current master.

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

No branches or pull requests

1 participant