M4L poly~ NULL pointer parameter... i need your help :-)

Stan's icon

Hello,

I have composed a M4L instrument patch only for isolating a reproduceable crash. It consists of a poly~ which receives midi from ableton live. The poly~ hosts only one instance of a very simple patch that does output a pure sine wave for dummy processing. The midi from ableton triggers a message ("TestCall TestSymbol") to a simple external, which does in fact nothing.
The problem is, that this TestCall-message sometimes forces the external to crash because of a corrupted t_symbol function parameter. Either the parameter is a NULL pointer or the t_symbol->t_name is a NULL pointer or it's a an illegal pointer even if it's not NULL.

This crash only occurs when the ableton live multiprocessor feature is enabled. And it's necessary to open more the one instance of the M4L instrument. I usually test with a number of at least four instances.

Please, has anyone an idea why this happens ? Is there anything obviously wrong with me ?

The zip file contains a frozen M4L device including the external and a ableton live set for testing. Also the c source code of the external is included.

Thank you for your attention. :-)

cheers
jan

Max Patch
Copy patch and select New From Clipboard in Max.

M4L instrument:

Max Patch
Copy patch and select New From Clipboard in Max.

Poly~ patch ("ExternalTestInsidePoly.maxpat"):

And the c source extract of the mentioned external. This function is called by the message "TestCall TestSymbol":

void ExternalTest_TestCall(t_ExternalTest *x, t_symbol *SymParam)
{
if(SymParam == NULL)
{
error("%s: TestCall parameter corrupt!",OBJECT_NAME);
return;
}

if(SymParam->s_name == NULL)
{
error("%s: TestCall parameter (s_name) corrupt!",OBJECT_NAME);
return;
}
}

Win XP32 SP3
Ableton Live 8.3.2
Max/MSP 5.1.9 (authorized via M4L)
Max/MSP SDK 5.1.7

HW:
System1: Intel Core2 T7200 with 2GB Ram
System2: Intel Core2 Quad 2.3GHz with 4GB Ram

4193.maxruntimewindowerror.png
png
Stan's icon

Please, could someone look at this issue ? I have spent a lot of time to investigate this. And it may be useful to know for M4L developers, I think. Perhaps I'm totally wrong...

Stan's icon

i have updated the external (previously written for max4) to the "new" function calls (e.g. class_new, class_addmethod, ...).
But this does not change anything.
The issue remains.

4209.ExternalTestABLETONSET.als
als
Stan's icon

And the source of the external.... nothing special, just for testing.

#include "ext.h"
#include "ext_obex.h"
#include "z_dsp.h"

void *ExternalTest_class;

#define OBJECT_NAME "ExternalTest~"

typedef struct _ExternalTest
{
  t_pxobject x_obj;
} t_ExternalTest;

void *ExternalTest_new(t_symbol *msg, short argc, t_atom *argv);
void ExternalTest_free(t_ExternalTest *x);
void ExternalTest_TestCall(t_ExternalTest *x, t_symbol *SymParam);

void *ExternalTest_class;

void main(void)
{
    t_class *c;
    c = class_new(OBJECT_NAME, (method)ExternalTest_new, (method)ExternalTest_free, (long)sizeof(t_ExternalTest), 0L , A_GIMME, 0);

    class_register(CLASS_BOX, c);
    class_addmethod(c, (method)ExternalTest_TestCall, "TestCall", A_SYM, 0);

    ExternalTest_class = c;
    post("I am the ExternalTest object");
}

void *ExternalTest_new(t_symbol *msg, short argc, t_atom *argv)
{
      t_ExternalTest *x = NULL;

    if (x = (t_ExternalTest *)object_alloc(ExternalTest_class))
    {
        object_post((t_object *)x, "a new %s object was instantiated: 0x%X", msg->s_name, x);
    }

  x->x_obj.z_misc |= Z_NO_INPLACE; 

  return (x);
}

void ExternalTest_free(t_ExternalTest *x)
{
  ;
}

void ExternalTest_TestCall(t_ExternalTest *x, t_symbol *SymParam)
{
  if(SymParam == NULL)
  {
    object_error((t_object *)x, "TestCall parameter corrupt!");
    return;
  }

  if(SymParam->s_name == NULL)
  {
    object_error((t_object *)x, "TestCall parameter (s_name) corrupt!");
    return;
  }
}
Andrew Pask's icon

We do not offer support for external development via standard support channels.
Is the problem evident in a Max 6 patcher or Max for Live device?

Cheers

Andrew

Stan's icon

Hello Nicolas,

ad 1) Yes, it is specific to M4L since the crash does not occur when multiprocessor support of Ableton Live is disabled.
ad 2) Yes, but the short answer was, that they don't give support for 3rd-party externals and I should paste my findings into the developer forum.

thanks.

Stan's icon

Hi Andrew,

I have tested this within the M4L-Runtime.

Installed is
Live 8.3.2
Max 5.1.9

Emmanuel Jourdan's icon

A few things I noticed, you seem to create a DSP object but there's:
- no dsp64 method, nor perform
- no dsp_free call in your ExternalTest_free

You also call class_register before adding the methods to your object. It should be at the end of the main method.

Stan's icon

Hello Emmanuel,

you are right. My original external uses the dsp functions (perform, dsp_free, etc).
Now I've built the same ExternalTest with your advice included. The issue remains the same.

Thanks for your answer!

#include "ext.h"
#include "ext_obex.h"

void *ExternalTest_class;

#define OBJECT_NAME "ExternalTest~"

typedef struct _ExternalTest
{
  t_object x_obj;
} t_ExternalTest;

void *ExternalTest_new(t_symbol *msg, short argc, t_atom *argv);
void ExternalTest_free(t_ExternalTest *x);
void ExternalTest_TestCall(t_ExternalTest *x, t_symbol *SymParam);

void *ExternalTest_class;

void main(void)
{
    t_class *c;
    c = class_new(OBJECT_NAME, (method)ExternalTest_new, (method)ExternalTest_free, (long)sizeof(t_ExternalTest), 0L , A_GIMME, 0);

    class_addmethod(c, (method)ExternalTest_TestCall, "TestCall", A_SYM, 0);

    ExternalTest_class = c;

    class_register(CLASS_BOX, c);

    post("I am the ExternalTest object...");
}

void *ExternalTest_new(t_symbol *msg, short argc, t_atom *argv)
{
      t_ExternalTest *x = NULL;

    if (x = (t_ExternalTest *)object_alloc(ExternalTest_class))
    {
        object_post((t_object *)x, "a new %s object was instantiated: 0x%X", msg->s_name, x);
    }

  return (x);
}

void ExternalTest_free(t_ExternalTest *x)
{
  ;
}

void ExternalTest_TestCall(t_ExternalTest *x, t_symbol *SymParam)
{
  if(SymParam == NULL)
  {
    object_error((t_object *)x, "TestCall parameter corrupt!");
    return;
  }

  if(SymParam->s_name == NULL)
  {
    object_error((t_object *)x, "TestCall parameter (s_name) corrupt!");
    return;
  }
}