node-dbus-next icon indicating copy to clipboard operation
node-dbus-next copied to clipboard

Bug? Process not terminating

Open frederikheld opened this issue 4 years ago • 8 comments

Hey,

if I initialize a system or session bus, the program won't terminate.

// example.js
'use strict' // happens without strict mode as well

const dbus = require('dbus-next')

const bus = dbus.systemBus() // happens with dbus.sessionBus() as well

When I run it on the terminal like this, it will run forever:

$ node example.js

I have to use Strg+C to terminate it.

Those are the versions I'm using:

Ubuntu: 20.10
node:  14.16.0
dbus-next: ^0.9.2

As I couldn't find any information that dbus needs to be closed/terminated/unset in some way, I assume that this is a bug.

I started to use dbus-next just a couple of days ago (when 0.9.2 was already released) but I still think that I didn't have this issue yesterday :-P But I'm not certain and I have no idea what could have introduced the issue.

Any ideas what's going on here?

Cheers Fred

frederikheld avatar Apr 06 '21 13:04 frederikheld

The bus runs in the background to process dbus messages. If you want it to stop, use bus.disconnect() when you are done with it and the process should terminate.

acrisci avatar Apr 06 '21 14:04 acrisci

Thanks for the quick reply!

I was looking for something like this, but trying it like this

'use strict'

const dbus = require('dbus-next')

const bus = dbus.systemBus()

bus.disconnect()

throws

Error [ERR_STREAM_WRITE_AFTER_END]: write after end
    at Socket.Writable.write (internal/streams/writable.js:292:11)
    at /path/to/repo/node_modules/dbus-next/lib/handshake.js:84:16
    at Socket.readable (/path/to/repo/node_modules/dbus-next/lib/readline.js:12:11)
    at Socket.emit (events.js:315:20)
    at emitReadable_ (internal/streams/readable.js:569:12)
    at processTicksAndRejections (internal/process/task_queues.js:79:21)
Emitted 'error' event on MessageBus instance at:
    at EventEmitter.<anonymous> (/path/to/repo/node_modules/dbus-next/lib/bus.js:159:12)
    at EventEmitter.emit (events.js:315:20)
    at Socket.<anonymous> (/path/to/repo/node_modules/dbus-next/lib/connection.js:86:10)
    at Socket.emit (events.js:315:20)
    at emitErrorNT (internal/streams/destroy.js:106:8)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) {
  code: 'ERR_STREAM_WRITE_AFTER_END'
}

It looks like something is still using that bus? But I have literally just reastarted my computer before I tried this and the example is as simple as I posted it here.

Is it intended that the bus is running forever? I haven't found any info on this in your examples.

Cheers Fred

frederikheld avatar Apr 06 '21 15:04 frederikheld

You've run into the unusual case of disconnecting a bus that hasn't connected yet. That's a bug I need to fix.

Is it intended that the bus is running forever?

Yes

acrisci avatar Apr 06 '21 15:04 acrisci

:-D okay. So I have to put some sleep in between to fix this :-D

This actually works :-)

'use strict'

const dbus = require('dbus-next')

const bus = dbus.systemBus()

setTimeout(() => {
    bus.disconnect()
}, 1000)

If this is intended, you should mention the need for explicitly calling disconnect() in the docs. I couldn't find anything about it in the examples and even the api docs don't say much about the importance of disconnect. For me it is unexpected that it is intended that bus never terminates and thus needs to be terminated explicitly.

But I'm beginning to understand the reasoning behind it and I think my approach of working with the MessageBus is wrong...

frederikheld avatar Apr 06 '21 15:04 frederikheld

Is this error I just got in any way related to the fact that dbus-next keeps connections open?

UnhandledPromiseRejectionWarning: DBusError: The maximum number of active connections for UID 1000 has been reached

I'm using nodemon to auto-restart my application during development. I guess this summed up the number of connections pretty quickly?

Where should I put dbus.disconnect()? I have a base class DBusObject from which all other classes inherit. DBusObject looks like this (very much simplified):

'use strict'

const dbus = require('dbus-next')

class DBusObject {
    constructor () {
        this.bus = dbus.systemBus()
    }
}

module.exports = DBusObject

All classes use this.bus to interact with the message bus. I don't understand the mechanism of dbus.systemBus(), I didn't expect to run into any connection limits.

Is there a better approach to do this? Should I connect to the bus and disconnect from it in every method call?

frederikheld avatar Apr 06 '21 22:04 frederikheld

Creating a bus is a heavyweight operation. You should only have one MessageBus for your whole application.

acrisci avatar Apr 06 '21 23:04 acrisci

So I should make it a global? I actually expected that dbus already is the global and dbus.systemBus() just returns the reference... Singleton style or something like that.

Do you know any real application based on dbus-next that I could look into to see how others are doing it?

frederikheld avatar Apr 06 '21 23:04 frederikheld

This library was originally written for mpris-service. The test suite was written to show how I intend to use the library. For other examples, use Github search.

https://github.com/search?p=1&q=dbus-next+language%3AJavaScript+language%3ATypeScript&type=Code

acrisci avatar Apr 07 '21 00:04 acrisci