Search code examples
cthriftglib

Why does my Thrift (c_glib) client fail with an "invalid pointer" error?


I'm creating a simple thrift server/client program in C (g_lib). This is how my thrift IDL file looks like:

namespace cpp tutorial

service Calculator {
    void ping(),
    binary getdata()    
}

And the implementation for getdata on the thrift server looks like this:

    static gboolean
    tutorial_calculator_handler_getdata (CalculatorIf  *iface,
                                      GByteArray        *_return,
                                      GError       **error)
    {
      THRIFT_UNUSED_VAR (iface);
      THRIFT_UNUSED_VAR (error);

      puts ("getdata()");

      GByteArray *gbarray;
      gint i;

      gbarray = g_byte_array_new ();
      for (i = 0; i < 100; i++)
          g_byte_array_append (gbarray, (guint8*) &i, 1);

      *_return = *gbarray;

      return TRUE;
    }

Now, on the client side, I'm calling the getdata as follows:

....
....
GByteArray *data;
....
....

if (!error && calculator_if_getdata (client, &data, &error)) {
  puts ("getdata()");      

}

Unfortunately, the client crashes with the following message in the calculator_if_getdata call:

*** Error in `./client': munmap_chunk(): invalid pointer: 0xb741742d ***
Aborted (core dumped)

Is this the correct way to send an array of integers from the server to client in thrift? What am i doing wrong here?


Solution

  • I figured it out after spending some time on it, here's the working handler and the client side implementation code:

    gboolean 
    tutorial_calculator_handler_getdata (CalculatorIf *iface,
                                     GByteArray ** _return,                                 
                                     GError **error)
    {
      THRIFT_UNUSED_VAR (iface);
      THRIFT_UNUSED_VAR (error);
    
      GByteArray *thing = g_byte_array_new();
      *_return = g_byte_array_new();
      guint8 i;
      for (i = 0; i < 10; i++){    
        g_byte_array_append (thing, (guint8*) &i, sizeof(guint8));
      }
    
      g_byte_array_append(*_return, (guint8*) thing->data, thing->len);
    
    
      return TRUE;
    }
    

    And the client side:

    GByteArray *data = g_byte_array_new();
    if (!error && calculator_if_getdata (client, &data, &error)) {
        puts ("getdata()");
        printf ("Data : %d\n", data);
        guint8 i;
        guint8 size = sizeof(guint8);
        for(i=0;i<10;i++)
          printf ("Data : %d\n", data->data[size*i]);
    
      }