Skip to content

Commit 4e93c4d

Browse files
committed
Add bus.disconnect and service.disconnect
Allow applications to disconnect their connections to dbus after they are done with them. Fixes #133 Changes required to make this happen: * Don't share bus objects: remove the code in lib/dbus.js that stores created Bus objects and returns them when a new bus is requested. Instead, create a new Bus object whenever one is requested. This allows each Bus object to disconnect itself without worrying that other objects are relying on it being connected. Note that at the C++ level, there is connection sharing going on because of the use of `dbus_bus_get`, but that isn't a problem because the dbus library is managing the sharing, and calling `Bus.prototype.disconnect` will correctly notify the underlying C++ that that particulary Bus object is no longer using its connection. * Remove the `dbus_connection_close` call. According to the documentation, this method should not be used when a connection is acquired using `dbus_bus_get`. Removing this prevents the error message "Applications must not close shared connections - see dbus_connection_close() docs. This is a bug in the application." noted in #133. See [dbus_bus_get][1] and [dbus_connection_close][2]. [1]: https://dbus.freedesktop.org/doc/api/html/group__DBusBus.html#ga77ba5250adb84620f16007e1b023cf26 [2]: https://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html#ga2522ac5075dfe0a1535471f6e045e1ee
1 parent 38c36b0 commit 4e93c4d

File tree

8 files changed

+94
-12
lines changed

8 files changed

+94
-12
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ bus.getInterface('com.example.Library', '/com/example/Library/authors/DAdams', '
136136
});
137137
```
138138

139+
#### `Bus.prototype.disconnect()`
140+
141+
Disconnect from DBus. This disconnection makes it so that Node isn't kept
142+
running based on this active connection. It also makes this bus, and all of its
143+
children (interfaces that have been retrieved, etc.) unusable.
144+
139145

140146
### Interface
141147

@@ -231,6 +237,13 @@ Remove (or unexpose) an object that has been created.
231237
service.removeObject(object);
232238
```
233239

240+
#### `Service.prototype.disconnect()`
241+
242+
Disconnect from DBus. This disconnection makes it so that Node isn't kept
243+
running based on this active connection. It also disconnects all of the objects
244+
created by this service.
245+
246+
234247
### ServiceObject
235248

236249
An object that is exposed over DBus.

lib/bus.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,19 @@ var Bus = module.exports = function(dbus, busName) {
5151

5252
util.inherits(Bus, events.EventEmitter);
5353

54+
Bus.prototype.disconnect = function(callback) {
55+
var self = this;
56+
57+
delete self.dbus.signalHandlers[self.connection.uniqueName];
58+
59+
self.dbus._dbus.releaseBus(self.connection);
60+
61+
self.connection = null;
62+
63+
if (callback)
64+
process.nextTick(callback);
65+
};
66+
5467
Bus.prototype.reconnect = function(callback) {
5568
var self = this;
5669

lib/dbus.js

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ var Utils = require('./utils');
66
var Bus = require('./bus');
77
var Service = require('./service');
88

9-
var busMap = {};
109
var serviceMap = {};
1110

1211
var enabledSignal = false;
@@ -41,14 +40,7 @@ DBus.Signature = Utils.Signature;
4140
DBus.prototype.getBus = function(busName) {
4241
var self = this;
4342

44-
// Return bus existed
45-
if (busMap[busName])
46-
return busMap[busName];
47-
48-
var bus = new Bus(self, busName);
49-
busMap[busName] = bus;
50-
51-
return bus;
43+
return new Bus(self, busName);
5244
};
5345

5446
DBus.prototype.parseIntrospectSource = function(source) {

lib/service.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,9 @@ Service.prototype.removeObject = function(object) {
3939

4040
self.bus.dbus._dbus.unregisterObjectPath(self.bus.connection, object.path);
4141
};
42+
43+
Service.prototype.disconnect = function() {
44+
var self = this;
45+
46+
self.bus.disconnect();
47+
};

src/connection.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,6 @@ namespace Connection {
274274

275275
uv_unref((uv_handle_t *)bus->loop);
276276

277-
if (dbus_connection_get_is_connected(connection))
278-
dbus_connection_close(connection);
279-
280277
dbus_connection_unref(connection);
281278
}
282279

test/client-disconnect.test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var tap = require('tap');
2+
var DBus = require('../');
3+
4+
var dbus = new DBus();
5+
var bus = dbus.getBus('session');
6+
7+
tap.plan(1);
8+
9+
var timeout = setTimeout(function() {
10+
tap.fail('Should have disconnected by now');
11+
process.exit();
12+
}, 1000);
13+
timeout.unref();
14+
15+
tap.ok('This is a dummy test. The real test is whether the tap.fail gets called on the timeout.');
16+
bus.disconnect();
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
var tap = require('tap');
2+
var DBus = require('../');
3+
4+
tap.plan(1);
5+
6+
var dbus = new DBus();
7+
var client = dbus.getBus('session');
8+
9+
var timeout = setTimeout(function() {
10+
tap.fail('Should have disconnected by now');
11+
process.exit();
12+
}, 1000);
13+
timeout.unref();
14+
15+
tap.ok('This is a dummy test. The real test is whether the tap.fail gets called on the timeout.');
16+
setTimeout(function() {
17+
client.disconnect();
18+
}, 50);
19+
20+
setTimeout(function() {
21+
var service = dbus.registerService('session', 'test.dbus.TestService');
22+
service.createObject('/test/dbus/TestService');
23+
setImmediate(function() {
24+
service.disconnect();
25+
});
26+
}, 100);

test/service-disconnect.test.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
var tap = require('tap');
2+
var DBus = require('../');
3+
4+
tap.plan(1);
5+
6+
var dbus = new DBus();
7+
var service = dbus.registerService('session', 'test.dbus.TestService');
8+
service.createObject('/test/dbus/TestService');
9+
10+
var timeout = setTimeout(function() {
11+
tap.fail('Should have disconnected by now');
12+
process.exit();
13+
}, 1000);
14+
timeout.unref();
15+
16+
tap.ok('This is a dummy test. The real test is whether the tap.fail gets called on the timeout.');
17+
setTimeout(function() {
18+
service.disconnect();
19+
}, 50);

0 commit comments

Comments
 (0)