Skip to content

Commit 5a63e03

Browse files
author
drswinghead
committed
fix system dbus connect hang #26
1 parent e9d29ec commit 5a63e03

File tree

7 files changed

+267
-1
lines changed

7 files changed

+267
-1
lines changed

tests/test_issue_26.cpp

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
build:
3+
moc tests/test_issue_26.cpp > tests/test_issue_26.moc
4+
g++ ./tests/test_issue_26.cpp -fPIC -lQt5DBus -I /usr/include/qt -I /usr/include/qt/QtDBus
5+
*/
6+
7+
#include <QtCore>
8+
#include <QtDBus>
9+
#include <qdbusutil_p.h>
10+
11+
12+
class Handler : public QObject {
13+
Q_OBJECT;
14+
public:
15+
Handler() : QObject(0) {
16+
}
17+
18+
public slots:
19+
void onmsg(QDBusMessage m) {
20+
qDebug()<<"hehhhehhhhhhhhh"<<m;
21+
}
22+
};
23+
24+
int main(int argc, char **argv) {
25+
QCoreApplication a(argc, argv);
26+
27+
auto sysbus = QDBusConnection::systemBus();
28+
QString service = "io.qtc.wxagent";
29+
QString path = "/io/qtc/wxagent/signals";
30+
QString iface = "io.qtc.wxagent.signals";
31+
// sysbus.registerService(service);
32+
33+
qDebug()<<sysbus.isConnected();
34+
Handler* h = new Handler();
35+
auto ret = sysbus.connect(QString(""), path, iface, "newmessage", h, SLOT(onmsg(QDBusMessage)));
36+
qDebug()<<ret<<sysbus.lastError()<<sysbus.isConnected();
37+
ret = sysbus.connect("", "", iface, "newmessage", h, SLOT(onmsg(QDBusMessage)));
38+
qDebug()<<ret<<sysbus.lastError()<<sysbus.isConnected();
39+
40+
{
41+
auto receiver = h;
42+
auto slot = SLOT(onmsg());
43+
auto interface = iface;
44+
QString name = "newmessage";
45+
46+
if (!receiver || !slot) {
47+
qDebug()<<"false1";
48+
}
49+
if (interface.isEmpty() && name.isEmpty()) {
50+
qDebug()<<"false2";
51+
}
52+
53+
if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) {
54+
qDebug("QDBusConnection::connect: interface name '%s' is not valid", interface.toLatin1().constData());
55+
} else {
56+
qDebug()<<"valid iface:"<<interface;
57+
}
58+
if (!service.isEmpty() && !QDBusUtil::isValidBusName(service)) {
59+
qDebug("QDBusConnection::connect: service name '%s' is not valid", service.toLatin1().constData());
60+
} else {
61+
qDebug()<<"valid bus name:"<<service;
62+
}
63+
if (!path.isEmpty() && !QDBusUtil::isValidObjectPath(path)) {
64+
qDebug("QDBusConnection::connect: object path '%s' is not valid", path.toLatin1().constData());
65+
} else {
66+
qDebug()<<"valid objpath"<<path;
67+
}
68+
}
69+
70+
qDebug()<<"enter main loop";
71+
return a.exec();
72+
}
73+
74+
#include "test_issue_26.moc"
75+

tests/test_issue_26.moc

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/****************************************************************************
2+
** Meta object code from reading C++ file 'bc.cpp'
3+
**
4+
** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0)
5+
**
6+
** WARNING! All changes made in this file will be lost!
7+
*****************************************************************************/
8+
9+
#include <QtCore/qbytearray.h>
10+
#include <QtCore/qmetatype.h>
11+
#if !defined(Q_MOC_OUTPUT_REVISION)
12+
#error "The header file 'bc.cpp' doesn't include <QObject>."
13+
#elif Q_MOC_OUTPUT_REVISION != 67
14+
#error "This file was generated using the moc from 5.7.0. It"
15+
#error "cannot be used with the include files from this version of Qt."
16+
#error "(The moc has changed too much.)"
17+
#endif
18+
19+
QT_BEGIN_MOC_NAMESPACE
20+
struct qt_meta_stringdata_Handler_t {
21+
QByteArrayData data[5];
22+
char stringdata0[30];
23+
};
24+
#define QT_MOC_LITERAL(idx, ofs, len) \
25+
Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
26+
qptrdiff(offsetof(qt_meta_stringdata_Handler_t, stringdata0) + ofs \
27+
- idx * sizeof(QByteArrayData)) \
28+
)
29+
static const qt_meta_stringdata_Handler_t qt_meta_stringdata_Handler = {
30+
{
31+
QT_MOC_LITERAL(0, 0, 7), // "Handler"
32+
QT_MOC_LITERAL(1, 8, 5), // "onmsg"
33+
QT_MOC_LITERAL(2, 14, 0), // ""
34+
QT_MOC_LITERAL(3, 15, 12), // "QDBusMessage"
35+
QT_MOC_LITERAL(4, 28, 1) // "m"
36+
37+
},
38+
"Handler\0onmsg\0\0QDBusMessage\0m"
39+
};
40+
#undef QT_MOC_LITERAL
41+
42+
static const uint qt_meta_data_Handler[] = {
43+
44+
// content:
45+
7, // revision
46+
0, // classname
47+
0, 0, // classinfo
48+
1, 14, // methods
49+
0, 0, // properties
50+
0, 0, // enums/sets
51+
0, 0, // constructors
52+
0, // flags
53+
0, // signalCount
54+
55+
// slots: name, argc, parameters, tag, flags
56+
1, 1, 19, 2, 0x0a /* Public */,
57+
58+
// slots: parameters
59+
QMetaType::Void, 0x80000000 | 3, 4,
60+
61+
0 // eod
62+
};
63+
64+
void Handler::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
65+
{
66+
if (_c == QMetaObject::InvokeMetaMethod) {
67+
Handler *_t = static_cast<Handler *>(_o);
68+
Q_UNUSED(_t)
69+
switch (_id) {
70+
case 0: _t->onmsg((*reinterpret_cast< QDBusMessage(*)>(_a[1]))); break;
71+
default: ;
72+
}
73+
}
74+
}
75+
76+
const QMetaObject Handler::staticMetaObject = {
77+
{ &QObject::staticMetaObject, qt_meta_stringdata_Handler.data,
78+
qt_meta_data_Handler, qt_static_metacall, Q_NULLPTR, Q_NULLPTR}
79+
};
80+
81+
82+
const QMetaObject *Handler::metaObject() const
83+
{
84+
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
85+
}
86+
87+
void *Handler::qt_metacast(const char *_clname)
88+
{
89+
if (!_clname) return Q_NULLPTR;
90+
if (!strcmp(_clname, qt_meta_stringdata_Handler.stringdata0))
91+
return static_cast<void*>(const_cast< Handler*>(this));
92+
return QObject::qt_metacast(_clname);
93+
}
94+
95+
int Handler::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
96+
{
97+
_id = QObject::qt_metacall(_c, _id, _a);
98+
if (_id < 0)
99+
return _id;
100+
if (_c == QMetaObject::InvokeMetaMethod) {
101+
if (_id < 1)
102+
qt_static_metacall(this, _c, _id, _a);
103+
_id -= 1;
104+
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
105+
if (_id < 1)
106+
*reinterpret_cast<int*>(_a[0]) = -1;
107+
_id -= 1;
108+
}
109+
return _id;
110+
}
111+
QT_END_MOC_NAMESPACE

tests/test_issue_26.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import sys
2+
3+
from PyQt5.QtCore import *
4+
from PyQt5.QtDBus import *
5+
6+
app = QCoreApplication(sys.argv)
7+
8+
sysbus = QDBusConnection.systemBus()
9+
10+
agent_service = 'io.qtc.wxagent'
11+
agent_service_path = '/io/qtc/wxagent'
12+
agent_service_iface = 'io.qtc.wxagent.iface'
13+
sysiface = QDBusInterface(agent_service, agent_service_path,
14+
agent_service_iface, sysbus)
15+
16+
service = agent_service
17+
path = '/io/qtc/wxagent/signals'
18+
iface = 'io.qtc.wxagent.signals'
19+
20+
class Handler(QObject):
21+
def __init__(self, parent=None):
22+
super(Handler, self).__init__(parent)
23+
return
24+
25+
@pyqtSlot(QDBusMessage)
26+
def onmsg(self, msg):
27+
return
28+
29+
30+
h = Handler()
31+
print(sysbus)
32+
# bug: blow line will block
33+
# fixed: http://stackoverflow.com/questions/38142809/pyqt-5-6-connecting-to-a-dbus-signal-hangs
34+
if True:
35+
sysbus.registerObject('/', h)
36+
sysbus.connect('', '', iface, 'newmessage', h.onmsg)
37+
print('runnnnnn')
38+
app.exec_()

tests/test_issue_26_rawdbus.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import pydbus
2+
from gi.repository import GObject
3+
4+
sysbus = pydbus.SystemBus()
5+
6+
systemd = sysbus.get('io.qtc.wxagent')
7+
8+
def handler1(a, b, c, d, e):
9+
print(11111, a, b, c, d, e)
10+
return
11+
12+
# help(sysbus.subscribe)
13+
sysbus.subscribe(iface='io.qtc.wxagent.signals', signal='newmessage', signal_fired=handler1)
14+
15+
GObject.MainLoop().run()

wxagent/qtoxkit.py

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ def __init__(self, identifier = 'anon', persist = True):
5454
if not os.path.exists(self.path):
5555
# copy current path qtox.ini to dst
5656
srcfile = os.path.dirname(__file__) + '/../etc/qtox.ini'
57+
if not os.path.exists(srcfile):
58+
qDebug('nodes source file not found: {} => {}'.format(srcfile, self.path))
59+
sys.exit(-1)
5760
distutils.file_util.copy_file(srcfile, self.path)
5861
self.qsets = QSettings(self.path, QSettings.IniFormat)
5962
pass

wxagent/tx2any.py

+24
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,24 @@ def __init__(self):
4242
return
4343

4444

45+
# seems fine in test, but here not fine.
46+
class HotfixDBusHandler(QObject):
47+
def __init__(self, parent=None):
48+
super(HotfixDBusHandler, self).__init__(parent)
49+
return
50+
51+
@pyqtSlot(QDBusMessage)
52+
def onmsg(self, msg):
53+
return
54+
55+
56+
def hotfixDBusBlock(sysbus):
57+
# hotfix issue #26
58+
# sysbus.registerObject('/hotfixidontknowwhy', HotfixDBusHandler()) # but can not help
59+
# why can just use `self` here?
60+
sysbus.registerObject('/hotfixidontknowwhy', self)
61+
return
62+
4563
#
4664
#
4765
#
@@ -83,6 +101,12 @@ def initDBus(self):
83101
if len(self.agent_service) == 0: raise 'need set self.agent_service value.'
84102
if len(self.agent_service_path) == 0: raise 'need set self.agent_service_path value.'
85103

104+
# hotfix issue #26
105+
# hotfixDBusBlock(self.sysbus)
106+
# self.sysbus.registerObject('/hotfixidontknowwhy', HotfixDBusHandler()) # but can not help
107+
# why can just use `self` here?
108+
self.sysbus.registerObject('/hotfixidontknowwhy', self)
109+
86110
if qVersion() >= '5.5':
87111
self.sysiface = QDBusInterface(self.agent_service, self.agent_service_path,
88112
self.agent_service_iface, self.sysbus)

wxagent/wxagent.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from concurrent.futures import ThreadPoolExecutor, Future, as_completed
1010

1111
from PyQt5.QtCore import *
12-
from PyQt5.QtNetwork import *
12+
from PyQt5.QtNetwork import QNetworkReply
1313
from PyQt5.QtDBus import *
1414

1515
from .wxcommon import *

0 commit comments

Comments
 (0)