MATLAB: Matlab crashes runing Multi Thread s-function with openGL

crashmexs-functionsimulink

Hi! I try to write a simple s-function with openGL/freeglut. I compile it within Visual Studio ( how to do it ). When i run my s-function in Simulink it works only the first time. The second attempt of running the model results in Matlab crash, but the matlab process steel exist in a memory.
May be there is a mistake with memory or thread manipulation? I find out that Matlab crashes at glutInit function
Will be very glad if somebody can help me because i have found almost no information about s-function used with multithreading or openGL.
Here is the code:
#define S_FUNCTION_NAME my_sf
#define S_FUNCTION_LEVEL 2
#include <simstruc.h>
#include <freeglut.h>
#include <Math.h>
#include <windows.h>
#include <process.h>
#include <stdio.h>
struct data_st {
unsigned ThreadId;
HANDLE hThread, hEvent;
};
void display() {
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer with current clearing color
// Define shapes enclosed within a pair of glBegin and glEnd
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(-0.8f, 0.1f); // Define vertices in counter-clockwise (CCW) order
glVertex2f(-0.2f, 0.1f); // so that the normal (front-face) is facing you
glVertex2f(-0.2f, 0.7f);
glVertex2f(-0.8f, 0.7f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex2f(-0.7f, -0.6f);
glVertex2f(-0.1f, -0.6f);
glVertex2f(-0.1f, 0.0f);
glVertex2f(-0.7f, 0.0f);
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.9f, -0.7f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.5f, -0.7f);
glColor3f(0.2f, 0.2f, 0.2f); // Dark Gray
glVertex2f(-0.5f, -0.3f);
glColor3f(1.0f, 1.0f, 1.0f); // White
glVertex2f(-0.9f, -0.3f);
glEnd();
glBegin(GL_TRIANGLES); // Each set of 3 vertices form a triangle
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.1f, -0.6f);
glVertex2f(0.7f, -0.6f);
glVertex2f(0.4f, -0.1f);
glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex2f(0.3f, -0.4f);
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex2f(0.9f, -0.4f);
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex2f(0.6f, -0.9f);
glEnd();
glBegin(GL_POLYGON); // These vertices form a closed polygon
glColor3f(1.0f, 1.0f, 0.0f); // Yellow
glVertex2f(0.4f, 0.2f);
glVertex2f(0.6f, 0.2f);
glVertex2f(0.7f, 0.4f);
glVertex2f(0.6f, 0.6f);
glVertex2f(0.4f, 0.6f);
glVertex2f(0.3f, 0.4f);
glEnd();
glFlush(); // Render now
}
void do_nothing(void) {
return;
}
unsigned __stdcall plot(struct data_st* data) {
char *argv[1];
int argc = 1;
argv[0] = strdup("Myappname");
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("Vertex, Primitive & Color"); // Create window with the given title
glutInitWindowSize(320, 320); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutDisplayFunc(do_nothing); // Register callback handler for window re-paint event
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
while (WaitForSingleObject(data->hEvent, 0) != WAIT_OBJECT_0) {
display();
glutMainLoopEvent();
}
//glutDestroyWindow( glutGetWindow() );
return(0);
}
/* Function: mdlInitializeSizes ===============================================
* Abstract:
* Setup sizes of the various vectors.
*/
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return; /* Parameter mismatch will be reported by Simulink */
}
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 1);
ssSetNumSampleTimes(S, 1);
/* specify the sim state compliance to be same as a built-in block */
ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);
ssSetNumDWork(S, 1);
ssSetDWorkWidth(S, 0, 1);
ssSetDWorkDataType(S, 0, SS_POINTER);
ssSetOptions(S,
SS_OPTION_WORKS_WITH_CODE_REUSE |
SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_USE_TLC_WITH_ACCELERATOR);
}
#define MDL_START
void mdlStart(SimStruct *S)
{
void **Ptrs = (void**)ssGetDWork(S, 0);
struct data_st* data;
data = (void*)malloc(sizeof(struct data_st));
Ptrs[0] = data;
data -> hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
data -> hThread = (HANDLE)_beginthreadex(NULL, 0, plot, data, 0, &(data->ThreadId));
if (data->hThread == 0)
return;
}
/* Function: mdlInitializeSampleTimes =========================================
* Abstract:
* Specifiy that we inherit our sample time from the driving block.
*/
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
ssSetModelReferenceSampleTimeDefaultInheritance(S);
}
/* Function: mdlOutputs =======================================================
* Abstract:
* y = 2*u
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
*y = 2.0 *(*uPtrs[0]);
}
/* Function: mdlTerminate =====================================================
* Abstract:
* No termination needed, but we are required to have this routine.
*/
static void mdlTerminate(SimStruct *S)
{
void **Ptrs = (void**)ssGetDWork(S, 0);
struct data_st* data;
data = Ptrs[0];
SetEvent(data->hEvent); // init event for thread stop
WaitForSingleObject(data->hThread, INFINITE); // wait thread to be finised
CloseHandle(data->hEvent);
CloseHandle(data->hThread);
free(data);
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif

Best Answer

I find the problem. glutInit function initialize glut library and it must be done only ones in currect matlab session. So i add a condition
if (glutGet(GLUT_INIT_STATE) == 0)
glutInit(&argc, argv);
that checks glut state