Argument array of strings

Peter Clifton pcjc2 at cam.ac.uk
Thu Oct 12 20:14:41 PDT 2006


Hi,

I've started the task of "porting" my glib dbus code to raw libdbus (for
sake of mainloop independance), and have run into difficulties with a
method:

  <interface name="org.seul.geda.pcb.actions">
    <method name="ExecAction">
      <arg direction="in" type="s" name="action" />
      <arg direction="in" type="as" name="args" />
      <arg direction="out" type="u" />
    </method>
  </interface>

I can get the "action" argument, I pick up the "args" argument as a
DBUS_TYPE_ARRAY, I can verify that it is an array of strings.

However:

What I can't seem to do is get the size of that array without the
program crashing.

I really want to know the size of the array before iterating over it, so
I can allocate memory for storing the strings.

When iterating over the "args" array of strings, I get the right strings
out, I just can't seem to determine how many are there before-hand.

Regards

Peter Clifton


static DBusHandlerResult
handle_exec_action( DBusConnection *connection, DBusMessage *message,
void *data)
{
  DBusMessage *reply;
  DBusMessageIter args;
  DBusMessageIter iter;
  DBusMessageIter subiter;
  DBusHandlerResult result;
  dbus_uint32_t retval;
  char *action_name;
  char **argv;
  int argc;
  int i;
  
  result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  
  if (!dbus_message_iter_init(message, &args))
    {
      fprintf(stderr, "Message has no arguments!\n");
      return result;
    }
  else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
    {
      fprintf(stderr, "Argument is not string!\n");
      return result;
    }
  else 
    dbus_message_iter_get_basic(&args, &action_name);
  printf("pcb_dbus: DEBUG: ExecAction called with action '%s'\n",
action_name);

  if (!dbus_message_iter_next(&args))
    {
      fprintf(stderr, "DBUS Method has no argument array!\n");
      return result;
    }
  else if (DBUS_TYPE_ARRAY != dbus_message_iter_get_arg_type(&args))
    {
      fprintf(stderr, "Argument is not array!\n");
      return result;
    }
  else if (DBUS_TYPE_STRING !=
dbus_message_iter_get_element_type(&args))
    {
      fprintf(stderr, "Argument array not strings\n");
      return result;
    }

 {
   char *signature;
   signature = dbus_message_iter_get_signature( &args );
   fprintf( stderr, "pcb_dbus: DEBUG: Signature of args = '%s'\n",
signature );
 }
  
  dbus_message_iter_recurse( &args, &subiter );
 {
   char *signature;
   signature = dbus_message_iter_get_signature( &subiter );
   fprintf( stderr, "pcb_dbus: DEBUG: Signature of subiter = '%s'\n",
signature );
 }
 
argc = 2; 

/* THIS LINE CRASHES */
  argc = dbus_message_iter_get_array_len( &args );

  fprintf( stderr, "pcb_dbus: DEBUG: Argument count is %i\n", argc );

  argv = malloc( argc * sizeof( char * ) );
  if ( argv == NULL )
    {
      fprintf(stderr, "malloc for argument array failed\n");
      return result;
    }

  i = 0;
  while ( i < argc )
    {
      dbus_message_iter_get_basic( &subiter, &argv[i] );
      dbus_message_iter_next( &subiter );
      printf( "  Got argument #%i = '%s'\n", i, argv[i] );
      i++;
    }
  fprintf( stderr, "pcb_dbus: DEBUG: about to execute action\n" ); 
  // TODO: Proper return value from actions
  hid_actionv( action_name, argc, argv ); 
  retval = 0;

  free( argv );

  reply = dbus_message_new_method_return(message);
  if (reply == NULL)
    {
      fprintf( stderr, "pcb_dbus: DEBUG: Couldn't create reply message
\n" );
      return result;
    }
  dbus_message_iter_init_append(reply, &iter);
  if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &retval))
    {
     fprintf(stderr, "pcb_dbus: DEBUG: Couldn't sent message, Out Of
Memory!\n");
     goto out;
    }

  if (!dbus_connection_send(connection, reply, NULL))
    {
     fprintf(stderr, "pcb_dbus: DEBUG: Couldn't send message, Out Of
Memory!\n");
     goto out;
    }

  result = DBUS_HANDLER_RESULT_HANDLED;
out:
  dbus_message_unref( reply );
  return result;
}


The crash is:

pcb_dbus: DEBUG: Method name was 'Introspect'
pcb_dbus: DEBUG: Method interface was
'org.freedesktop.DBus.Introspectable'
pcb_dbus: DEBUG: Method call message
pcb_dbus: DEBUG: Method name was 'GetFilename'
pcb_dbus: DEBUG: Method interface was 'org.seul.geda.pcb'
pcb_dbus: DEBUG: Method call message
pcb_dbus: DEBUG: Method name was 'ExecAction'
pcb_dbus: DEBUG: Method interface was 'org.seul.geda.pcb.actions'
pcb_dbus: DEBUG: ExecAction called with action 'SaveTo'
pcb_dbus: DEBUG: Signature of args = 'as'
pcb_dbus: DEBUG: Signature of subiter = 's'

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1219139920 (LWP 8754)]
0xb7eec7d6 in dbus_error_has_name () from /usr/lib/libdbus-1.so.3
(gdb) bt
#0  0xb7eec7d6 in dbus_error_has_name () from /usr/lib/libdbus-1.so.3
#1  0x080bda1b in handle_dbus_message (connection=0x830abf8, 
    message=0x8305770, data=0x0) at dbus.c:164
#2  0xb7ef4a3b in dbus_message_new_method_return ()
   from /usr/lib/libdbus-1.so.3
#3  0xb7ee793a in dbus_connection_dispatch ()
from /usr/lib/libdbus-1.so.3
#4  0xb7ee7d38 in dbus_connection_borrow_message ()
   from /usr/lib/libdbus-1.so.3
#5  0x080bd2d5 in pcb_dbus_setup () at dbus.c:407
#6  0x08090722 in main (argc=Cannot access memory at address 0x0
) at main.c:774
(gdb) 


However... this stack doesn't look right to me.. Still.. it is 4AM, and
I'm _very_ tired now!


Peter C.




More information about the dbus mailing list