X-forwarded PyQt application hanging due to separate UHD application
23:25 01 Dec 2025

I'm working on a project that uses an X440 radio from Ettus Research, which relies on UHD under the hood for its API. My application has three main components:

  1. C++ files that handle all of the UHD/USRP calls and the high-speed interfaces between the radio and the stream endpoints.

  2. A Python script that uses NiceGUI to send commands to the C++ application to control the behavior of the USRP.

  3. A Python script that uses PyQt to display a basic spectrum analyzer view of a portion of the samples received from the radio. These samples are streamed over ZMQ at a low enough rate to avoid overflow.

All of these scripts are running on a headless RHEL9 machine, which I access via SSH.


I'm experiencing an issue between parts 1 and 3 when I try to use the C++ files with the spectrum analyzer GUI.

If I start the spectrum analyzer Python script before calling the uhd::usrp::multi_usrp::make() function in my C++ application, the spectrum analyzer works as expected. The X-forwarded window pops up, and I can interact with it normally. Additioanlly, the spectrum analyzer continues to work after I run uhd::usrp::multi_usrp::make().

However, if I run the spectrum analyzer Python script after calling uhd::usrp::multi_usrp::make(), the GUI goes through the setup steps but never displays. Furthermore, I can't stop the script with CTRL-C in the console. The only way to get the script to respond is to kill the C++ application. Once the C++ application is killed, the spectrum analyzer GUI pops up correctly.

Because of the high data rate from the X440, UHD is using DPDK under the hood. I am not sure if that's relevant, but I wanted to mention it.


What could be causing this? I've tried debugging on the Python side, but I suspect it's getting hung at the system level, so Python debugging hasn't been effective.


Minimal GUI Code that reproduces the issue:

from pyqtgraph.Qt import QtWidgets, QtCore

class myGui(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        # Layout
        layout = QtWidgets.QVBoxLayout(self)
        ctrl_layout = QtWidgets.QHBoxLayout()
        layout.addLayout(ctrl_layout)
        print("Done here") # This line prints but then the app never shows if 
                            # started after the C++ applications



def main():
    print("main")
    app = QtWidgets.QApplication([])
    gui = myGui()
    gui.resize(1200, 900)
    gui.show()
    app.exec()


if __name__ == "__main__":
    main()

Minimal C++ code that will cause the hang if the GUI code is started after the USRP is made:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 


int UHD_SAFE_MAIN(int argc, char* argv[]) {
    // minimal config for demonstration
    uhd::usrp::multi_usrp::sptr usrp_;
    std::cout << "Before usrp, waiting 20 seconds" << std::endl; //GUI wont hang here
    std::this_thread::sleep_for(std::chrono::seconds(20));
    std::cout << "Making USRP" << std::endl;
    usrp_ = uhd::usrp::multi_usrp::make("addr=192.168.10.2, second_addr=192.168.20.2," 
        "mgmt_addr=192.168.200.2,use_dpdk=1, master_clock_rate=500e6,"
        "converter_clock_rate=4e9");

    std::cout << "Finished making USRP, waiting 20 seconds" << std::endl; //GUI now hangs
    std::this_thread::sleep_for(std::chrono::seconds(20));
    return 0;
}
python pyqt dpdk xserver uhd