Skip to content

Subscribing to multiple events causes several issues #4

@runeerle42

Description

@runeerle42

Hi, I'm using go-modemmanager to handle outgoing and incoming SMS and voice calls.

I have two issues that I don't know why occur. Both are related to subscribing to events. The first is that subscribing to several different event types causes all channels to receive all events. The second is that unsubscribing leaks lots of memory.
Here is a code example with only the important parts:

voice, err := modem.GetVoice()
messageHandle, err := modem.GetMessaging()

voiceDbus := voice.SubscribeCallAdded()
messageDbus := messageHandle.SubscribeAdded()

go func() {
	for true {
		select {
		case dbusVoice := <-voiceDbus:
			log.Printf("case dbusVoice: %v\n", dbusVoice)
		case dbusMessage := <-messageDbus:
			log.Printf("case dbusMessage: %v\n", dbusMessage)
		}
	}
}
...
smsSend, errSMS := messageHandle.CreateSms(selfNumber, sendString) // Send SMS to myself
smsDbus := smsSend.SubscribePropertiesChanged()
go func() {
	for true {
		select {
		case dbusSMS := <-smsDbus:
			log.Printf("case dbusSMS: %v\n", dbusSMS)
		case <-time.After(time.Minute * 1):
			smsSend.Unsubscribe()
			return
		}
	}
}
// The outgoing SMS
smsSend.Send()

First issue:

// Output:
case dbusVoice: &{:1.6207 /org/freedesktop/ModemManager1/Modem/0 org.freedesktop.ModemManager1.Modem.Messaging.Added [/org/freedesktop/ModemManager1/SMS/688 false]}
case dbusMessage: &{:1.6207 /org/freedesktop/ModemManager1/Modem/0 org.freedesktop.ModemManager1.Modem.Messaging.Added [/org/freedesktop/ModemManager1/SMS/688 false]}

case dbusSMS: &{:1.6207 /org/freedesktop/ModemManager1/SMS/688 org.freedesktop.DBus.Properties.PropertiesChanged [org.freedesktop.ModemManager1.Sms map[MessageReference:@u 148 State:@u 5] []]}
case dbusVoice: &{:1.6207 /org/freedesktop/ModemManager1/SMS/688 org.freedesktop.DBus.Properties.PropertiesChanged [org.freedesktop.ModemManager1.Sms map[MessageReference:@u 148 State:@u 5] []]}
case dbusMessage: &{:1.6207 /org/freedesktop/ModemManager1/SMS/688 org.freedesktop.DBus.Properties.PropertiesChanged [org.freedesktop.ModemManager1.Sms map[MessageReference:@u 148 State:@u 5] []]}

// The same SMS returning:
case dbusSMS: &{:1.6207 /org/freedesktop/ModemManager1/Modem/0 org.freedesktop.ModemManager1.Modem.Messaging.Added [/org/freedesktop/ModemManager1/SMS/689 true]}
case dbusVoice: &{:1.6207 /org/freedesktop/ModemManager1/Modem/0 org.freedesktop.ModemManager1.Modem.Messaging.Added [/org/freedesktop/ModemManager1/SMS/689 true]}
case dbusMessage: &{:1.6207 /org/freedesktop/ModemManager1/Modem/0 org.freedesktop.ModemManager1.Modem.Messaging.Added [/org/freedesktop/ModemManager1/SMS/689 true]}

Second and main issue:
There are more and more hanging signals that never quit. It only happens after smsSend.Unsubscribe() is called.

//Wait for the listener to go away
time.Sleep(time.Second * 65)

// Send messages and print all running stack traces:
for true {
	smsSend, errSMS := messageHandle.CreateSms(selfNumber, sendString) // Send SMS to myself
	smsSend.Send()
	time.Sleep(time.Second * 30)
	buf := make([]byte, 1<<16)
	runtime.Stack(buf, true)
	log.Printf("Stack trace:\n%v", string(buf))
}

After ~10 messages the number of hanging goroutines starts to grow and all hang in "deferredDeliver":

// Output:
Stack trace:
goroutine 258 [select, 1 minutes]:
github.com/godbus/dbus/v5.(*signalChannelData).deferredDeliver(0x4000624b60, 0x40001e2550)
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:318 +0x88
created by github.com/godbus/dbus/v5.(*signalChannelData).deliver
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:313 +0xf8

goroutine 188 [select, 2 minutes]:
github.com/godbus/dbus/v5.(*signalChannelData).deferredDeliver(0x4000624b60, 0x40005b4280)
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:318 +0x88
created by github.com/godbus/dbus/v5.(*signalChannelData).deliver
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:313 +0xf8

goroutine 158 [select, 2 minutes]:
github.com/godbus/dbus/v5.(*signalChannelData).deferredDeliver(0x4000624b60, 0x40001e2230)
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:318 +0x88
created by github.com/godbus/dbus/v5.(*signalChannelData).deliver
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:313 +0xf8

goroutine 195 [select, 1 minutes]:
github.com/godbus/dbus/v5.(*signalChannelData).deferredDeliver(0x4000624b60, 0x40005b41e0)
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:318 +0x88
created by github.com/godbus/dbus/v5.(*signalChannelData).deliver
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:313 +0xf8

goroutine 168 [select, 2 minutes]:
github.com/godbus/dbus/v5.(*signalChannelData).deferredDeliver(0x4000624b60, 0x400017e0f0)
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:318 +0x88
created by github.com/godbus/dbus/v5.(*signalChannelData).deliver
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:313 +0xf8

goroutine 247 [select]:
github.com/godbus/dbus/v5.(*signalChannelData).deferredDeliver(0x4000624b60, 0x40001e25a0)
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:318 +0x88
created by github.com/godbus/dbus/v5.(*signalChannelData).deliver
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:313 +0xf8

goroutine 174 [select, 2 minutes]:
github.com/godbus/dbus/v5.(*signalChannelData).deferredDeliver(0x4000624b60, 0x400017e3c0)
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:318 +0x88
created by github.com/godbus/dbus/v5.(*signalChannelData).deliver
	/home/.../go/pkg/mod/github.com/godbus/dbus/v5@v5.0.3/default_handler.go:313 +0xf8

This crashes my program with OOM since a new SubscribePropertiesChanged/Unsubscribe() pair was made for each message. I believe it uses exponentially more memory because Unsubscribe() fails to trigger close() on the channel. That is, the smsDbus channel never closes as a separate test show that it still receives events even after Unsubscribe() is called.

I'm not sure if I do something wrong or if the error is somewhere else. Hope you can help me :)

Regards
Rune

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions