Skip Menu |

This queue is for tickets about the Net-DBus CPAN distribution.

Report information
The Basics
Id: 21337
Status: resolved
Priority: 0/
Queue: Net-DBus

People
Owner: Nobody in particular
Requestors: emmanuel.rodriguez [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 0.33.3
Fixed in: (no value)



Subject: Failure to send a dictionary type
NOTE: This bug requires that the patch listed in the bug '#21212: Net::DBus::Binding::Message missing variant type' is applied before. The perl bindings for Net::DBUS crash without an error message when a dictionary of type variant is being passed through DBUS. This problem only happens when there is data in the dictionary. Sending an empty dictionary causes no problem. A test case is attached to this bug.
Subject: dbus-test-case.pl
#!/usr/bin/perl =head1 NAME dbus-test-case.pl - Sample DBUS test case. =head1 SYNOPSIS dbus-test-case.pl =head1 DESCRIPTION Sample program used to demonstrate a failure with the Net::DBUS API. The failure happens when a dictionary of type variant is passed through the bus. =head1 AUTHOR Emmanuel Rodriguez < emmanuel.rodriguez@gmail.com > =cut use strict; use warnings; use Net::DBus; # Main entry point exit main(); # # Main entry point of the program # sub main { my $dbus = Net::DBus->session; my $service = $dbus->get_service("org.freedesktop.Notifications"); my $object = $service->get_object("/org/freedesktop/Notifications"); print "Before\n"; # Send and notification $object->Notify( "dbus-test", # Application name 0, # replaces_id (0 -> nothing) 'gtk-connect', #app_icon ("" -> no icon) 'Test event', # summary "This is a test to see if DBUS works nicely in Perl.\nI hope that this works.", # body [], # actions ## ## This is where problem seems to be. ## The hashref is meant to be past as a dictionary of type variant. ## For more details on the method signature see : ## http://www.galago-project.org/specs/notification/0.9/x408.html ## ## For more details on the expected type of this particular field see: ## http://www.galago-project.org/specs/notification/0.9/x344.html ## { x => 100, y => 200, }, # hints 5_000 # expire_timeout in milliseconds ); # Expected to be printed print "After\n"; return 0; }
From: emmanuel.rodriguez [...] gmail.com
I noticed that this failure happens when one of the values passed is an integer. If the value passes is a string the method call works fine. Thus if the test case is modified to pass the following dictionary the code will work: { 'desktop-entry' => 'rhythmbox.desktop', 'category' => 'close', } Using the following wrapper has no effect: { x => dbus_variant(100), y => dbus_variant(200), }, While the following code: { x => dbus_int32(100), y => dbus_int32(200), }, Gives the following warnings and has no effect: Array or variant type requires that type variant be written, but int32 was written Array or variant type requires that type variant be written, but int32 was written
From: emmanuel.rodriguez [...] gmail.com
The problem seems to be in the module Net::DBus::Binding::Iterator within the method guess_type. Exactly where the following comment can be found: # XXX Should we bother trying to guess integer & floating point types ? The method guess_type doesn't guess the type when dealing with simple scalar values and assumes that everything is a string, probably this wouldn't be a problem with basic DBUS types but with a DBUS variant it doesn't work too well, specially with strong typed languages. There should be a way to put a type on the values in order to bypass the guessing stage. I though that wrapping my values with the a call to 'dbus_int32' will do it, but the bindings keep complaining, see my previous comment.
From: emmanuel.rodriguez [...] gmail.com
Here is a patch that provides a more flexible work around. The solution is not perfect as types are still guessed. In my opinion the best way to do this is to let the user specify the data types. If no data types are specified then we could revert to a guess. But guessing has it's problems in particular with the integers types which have more than 5 possible data types and with boolean values which are undistinguishable from integers in perl.
--- Iterator.pm 2006-07-06 00:34:37.000000000 +0200 +++ /usr/local/lib/perl/5.8.7/Net/DBus/Binding/Iterator.pm 2006-09-09 09:55:00.000000000 +0200 @@ -522,6 +522,21 @@ # XXX Should we bother trying to guess integer & floating point types ? # I say sod it, because strongly typed languages will support introspection # and loosely typed languages won't care about the difference + + # XXX This is causing too much problems when the data is of type variant! + + # XXX This patch is still not perfect, for instance integers are asume to be int32 + # there's no way into passing a boolean. The best way is to let the user + # choose the data type. + + # Regexps copied from perlfaq4 'How do I determine whether a scalar is a number/whole/integer/float?' + if ($value =~ /\D/) {return &Net::DBus::Binding::Message::TYPE_STRING;} + elsif ($value =~ /^[+-]?\d+$/) {return &Net::DBus::Binding::Message::TYPE_INT32;} + elsif ($value =~ /^-?\d+\.?\d*$/) {return &Net::DBus::Binding::Message::TYPE_DOUBLE;} + elsif ($value =~ /^-?(?:\d+(?:\.\d*)?|\.\d+)$/) {return &Net::DBus::Binding::Message::TYPE_DOUBLE;} + elsif ($value =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) {return &Net::DBus::Binding::Message::TYPE_DOUBLE;} + + # Assume a string return &Net::DBus::Binding::Message::TYPE_STRING; } }
From: DANBERR [...] cpan.org
On Sat Sep 09 04:01:36 2006, emmanuel.rodriguez@gmail.com wrote: Show quoted text
> Here is a patch that provides a more flexible work around. The solution > is not perfect as types are still guessed. In my opinion the best way to > do this is to let the user specify the data types. If no data types are > specified then we could revert to a guess. But guessing has it's > problems in particular with the integers types which have more than 5 > possible data types and with boolean values which are undistinguishable > from integers in perl.
It should already be possible to explicitly mark the data type when passing in a scalar which you don't want interpreted as a string. Your example above was nearly correct - you need to use both dbus_variant & dbus_int32 though - the variant is merely a container type, so you need to specify the type of the value contained too. Try using: x => dbus_variant(dbus_int32(3)) I've not tested it yet, but I'll add some more test cases to ensure this does work correctly. I don't really want to extend the guess_type method beyond distinguishing scalar/array/hash, because as you note its basically impossible to decide between the 6 integer data types.
From: emmanuel.rodriguez [...] gmail.com
Show quoted text
> It should already be possible to explicitly mark the data type when > passing in a scalar which you don't want interpreted as a string. Your > example above was nearly correct - you need to use both dbus_variant & > dbus_int32 though - the variant is merely a container type, so you need > to specify the type of the value contained too. Try using: > > x => dbus_variant(dbus_int32(3)) > > I've not tested it yet, but I'll add some more test cases to ensure this > does work correctly. > > I don't really want to extend the guess_type method beyond > distinguishing scalar/array/hash, because as you note its basically > impossible to decide between the 6 integer data types.
Yes it worked fine, thanks. It's a pity that I didn't think of wrapping the value through both methods! You can forget about my patch and close this bug. Sorry for the inconvenience and thanks once more.
Closing ticket based on previous comment showing dbus_variant(dbus_int32(4)) works as desired.