DBus : transmit a Data Array but crash

时间:2015-08-06 13:53:52

标签: dbus

I would like to transmit a data array from one application to the other via DBus.

My code as below:

server.c:

/* server.c */

#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

DBusHandlerResult filter_func(DBusConnection *connection, 
  DBusMessage *message, void *usr_data)
{
    DBusMessage *reply;
    dbus_bool_t handled = false;
    char *pReadData;
    unsigned char len;
    unsigned char i;

    DBusError dberr;

    dbus_error_init(&dberr);

     printf("pReadData = %x\n", (unsigned int)pReadData);

   if(FALSE == dbus_message_get_args(message, &dberr, DBUS_TYPE_ARRAY,
 DBUS_TYPE_BYTE, &pReadData, &len,  DBUS_TYPE_INVALID) && 0 != len)
 {
   //printf("len = %d\n");
   //printf("receiver data error\n");
   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }

  if(0 == len)
    return DBUS_HANDLER_RESULT_HANDLED;

  printf("len = %d, ", len);

  for( i = 0; i < len; i++)
     printf("%#2x ", (unsigned char)pReadData[i]);
  printf("\n");    
  handled = true;

  printf("pReadData = %x\n", (unsigned int)pReadData);

  /*if one free pReadData, it will crash!*/
//dbus_free_string_array((char**)&pReadData);

   return (handled ? DBUS_HANDLER_RESULT_HANDLED :
  DBUS_HANDLER_RESULT_NOT_YET_HANDLED);

}/*filter_func*/


int main(int argc, char *argv[])
{
    DBusError dberr;
    DBusConnection *dbconn;

     dbus_error_init(&dberr);
     dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);

    if (!dbus_connection_add_filter(dbconn, filter_func, NULL, NULL)) {
       return -1;
    }

    dbus_bus_add_match(dbconn,      "type='signal',interface='gaiger.Drstein.Demonstration'", &dberr);

     while(dbus_connection_read_write_dispatch(dbconn, -1)) {
         /* loop */
     }

      return 0;
}/*main*/

And client.c

#include <dbus/dbus.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int db_send(DBusConnection *dbconn)
{
     DBusMessage *dbmsg;
     char *pSendData;
     unsigned char len;
     unsigned char i;

     pSendData = (char *)malloc(256);

     dbmsg = dbus_message_new_signal("/client/signal/Object", 
       "gaiger.Drstein.Demonstration", "Test");

     len = 6;
     for(i = 0; i < len; i++)
     pSendData[i] = (unsigned char)i;

     if (!dbus_message_append_args(dbmsg, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, 
    &pSendData,  len, DBUS_TYPE_INVALID)) 
    {
       return -1;
    }

    if (!dbus_connection_send(dbconn, dbmsg, NULL)) {
         return -1;
    }

    dbus_connection_flush(dbconn);
    printf("send message : len = %d, ", len );

    for( i = 0; i < len; i++)
      printf("%#x ", (unsigned char)pSendData[i]);

    printf("\n"); 
      dbus_message_unref(dbmsg);    
    free(pSendData);

    return 0;
 }/**/


 int main(int argc, char *argv[])
 {
    unsigned int i;
    DBusError dberr;
    DBusConnection *dbconn;

    dbus_error_init(&dberr);

     dbconn = dbus_bus_get(DBUS_BUS_SESSION, &dberr);

 #if(1)    
     for(i = 0; i < 3; i++)
     db_send(dbconn);
 #else
     while(dbus_connection_read_write_dispatch(dbconn, -1)) {
       db_send(dbconn);
     }
 #endif  

     dbus_connection_unref(dbconn);
     return 0;
 }

The code works in Ubuntu 14.4, x86-64, but it crash in printing received data in Fedora 21, x86-32, virtual machine.

For the line :

if(FALSE == dbus_message_get_args(message, &dberr, DBUS_TYPE_ARRAY, 
DBUS_TYPE_BYTE, &pReadData, &len,  DBUS_TYPE_INVALID) && 0 != len)

I know the pointer pReadData would be allocated by dbus itself, the address value after this line is 0x90000 in Fedora 21, it is very odd number.

How should I do to avoid crash but print received data values in Fedora 21 x86 32bit?

Thank your help.

1 个答案:

答案 0 :(得分:1)

dbus_message_get_args的文档说明dbus_message_iter_get_fixed_array,我们看到len参数是指向整数的指针(因为在DBus“数组中有最大长度定义为2到26次幂或67108864(64 MiB)。“)但是您传递的指针指向unsigned char。在服务器的第15行使用int len;

此外,您不应该假设int和指针的大小相同,而是使用long来打印指针。

printf("pReadData = %lx\n", (unsigned long)pReadData);