App QNX 6.3 to 6.5.0

Dear all,

Couple months ago i ported my app from QNX4.25 to QNX6.3 with the mig4nto lib and mig4nto-procmgr. After some modifications, everything was ok as message-passing functionality.

Today, i’m working with QNX6.5. I modified a little bit mig4nto lib and mig4nto-procmgr (names of pthread members for example) and my boot image to fit with QNX6.5. At this step it’s ok.

However, now my app doesn’t work at all and i don’t understand why. I explain :

The start point is an application named “Starter”. Its job is to launch 9 other processes one by one sequentially with always the same sequence :

Starter “spawn” the process → Send (with the old Sendmx function) an init message to the client process → client process does a receive() and after initialization of intern modules a reply() to Starter process → Starter acks the message and continue.

I’m just using Send/Receive/Reply primitives of message passing.
My problem now is message passing works randomly or quasi never. Sendmx function returns -1 as if the process client doesn’t exist or something else.
I notice the initialization of intern modules is longer than QNX6.3 (and longer than QNX4.25). Is there a timeout in message passing between send/reply loop ?

Thx for help or any ideas.

Ade

Ade,

I’m not 100% sure exactly what you have done in terms of the boot image.

But virtually nothing compiled in QNX 6.3 is compatible with QNX 6.5. In other words you will need to recompile all your code under 6.5. Furthermore, any QNX library/executable etc in the boot image from 6.3 won’t work in 6.5. You need to replace all of them with the equivalent library/executable from 6.5

In other words you must recompile all your code for 6.5 AND you must build an entirely new boot image using 6.5 libraries/executables. Is that what you have done?

Tim

Hi Tim,

Yes i have rebuilt all my code under 6.5. My steps were the following :

  1. Adapt my boot image (.build) to 6.5 with libc.so.3, io-pkt instead of io-net and so on. Do a mkifs to flash after my Compact Flash with the boot image (.ifs).

  2. Rebuild mig4nto lib and its manager under 6.5. It generates libmig4nto.a and mig4nto-procmgr for 6.5. I have modified the lib to handle fixed priority when i call mig4nto_init () function by passing _NTO_CHF_FIXED_PRIORITY.

  3. Recompile all my application source under 6.5.

  4. Test my little app Client/Server to verify process creation and message passing with mig4nto lib. Test is ok.

  5. Install my “big” app and try to start it…

Ade

Take a look at http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/lib_ref/n/name_attach.html.
Moke sure you are filtering the messages you receive to properly handle the _IO_CONNECT messages.

Hi Space,

I can try to modify the mig4nto lib but why i should handle _IO_CONNECT messages under 6.5 if under 6.3 it was ok ? AFAIK there is no modification about name_attach function and others between 6.3 and 6.5.

Ade

Ade,

It sounds like you’ve done all the right steps. The fact that your test app client/server works fine is a good indication that you have everything compiled correctly for 6.5.

Now as for your main app…

  1. In your original post you mentioned you modified the migno library to do fixed priorities (_NTO_CHF_FIXED_PRIORITY). Was there a specific reason you did this? Without priority inheritance you may be starving important threads with lesser threads which could explain why you see ‘delays’ under 6.5 you didn’t see under 6.3. Now it’s not clear whether you did this in 6.3 too but my question is, are you using the same hardware under 6.5 that you did in 6.3? Including multi-core support (assuming your CPU is multi-core in either/both cases). I’m trying to figure out if the hardware has changed between 6.3 and 6.5 or multi-core support which may be affecting how things are running.

  2. Since you have the source code for the migno library (and server) you should be able to figure out exactly what the sendmx returning -1 means (ie print out the errno and figure out what error you are getting). Then potentially add print code to the migno server on the server side if required to see when connections are made. Or maybe you can debug in the Eclipse environment if you have that set up and can get the error to easily occur there.

Tim

P.S. Note it would be handy to see the actual code snippet that launches all your processes including the message sending.

Tim,

Thx for your replies. Here, what i can say :

  1. Under QNX4.25 the main app was configured with fixed priority so i simply reproduce the way it was running. At the beginning under 6.3, i tried priority inheritance. The main issue was priority switching. I explain :
    All processes are configure (priority is set to X value around 30) and launch with the Starter process which is start from shell (priority at 10 by default). With inheritance, a high process (priority 30) was switching to priority 10 and then back to 30 if another high process communicate with it for example. So sometimes, they were preempted by lower processes.
    The fact is fixed priority works well under 6.3, my main app is slower than 4.25 during init phase but it works.
    The hardware is still the same nothing at all changed. Same CPU (AMD LX800 on MSM800BEV), same CompactFlash…I’m working on PC/104 modules.

  2. Yes, i will try to print errno.

PS : yes I will post code snippet when i could but not immediately because i’m not at my office for the moment…

Wrong!

From the 6.5 Release Notes, found here:
qnx.com/developers/articles/rel_4222_41.html

“Binaries created with QNX Momentics 6.3 should be compatible with QNX SDP 6.4.* or 6.5.0”

Note the word should.

Also it only talks about the 2.95.3 version of the compiler. It’s very buggy and old. We’ve always used the 3.3.5 version that is newer and better. Not sure the shared libraries for that version are supported between 6.3 and 6.4X.

My personal experience has been that a lot of stuff hasn’t worked when moving between versions. I’ve even had problems bringing binaries from 6.3.0 SP3 to 6.32. So our rule of thumb is everything must be recomplied.

Tim

Tim,

For reminder, the Starter does the following steps (in time fashion) :

  1. Starter spawn Process A
  2. Process A waits for Starter init message on “receivemx” primitive
  3. Starter sends init message
  4. Process A replies and runs
  5. Starter spawn Process B and so on

Here is the Starter source :

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#ifndef __QNXNTO__
#include <conio.h>
#else
#include <mig4nto.h>
#endif
#include <string.h>
#ifdef ESSAIS_VENT	
#include <process.h>
#endif

#include "dgo.h"
#include "lgap_type.h"
#include "lgbp_type.h"

#include "Acq_paramDef.h"
#include "PcanMess.h"
#include "Pio_Mess.h"
#include "Pacqima_Mess.h"
#include "Pst_InitQnx.h"
#include "LibTrace.h"
#include "LibParam.h"
#include "LibCom.h"
#include "LibStimuliClavier.h"
#include "LibTimeType.h"
#include "cdgo_fichiersCalib.h"
#include "LibParamCalib.h"
#include "Pfglc.h"
#include "Pasd.h"
#include "Acq_Acqima.h"
#include "ass_iface.h"
#include "ats_iface.h"
#include "epv_iface.h"
#include "iris_iface.h"
#include "mefa_iface.h"
#include "remc_iface.h"
#include "atd_iface.h"
#include "gau_iface.h"
#include "ldc_iface.h"
#include "mefg_iface.h"
#include "fg200_iface.h"
#include "fg25_iface.h"

#include "P25_iface.h"
#include "LibTimeType.h"
#include "LibMes_iface.h"
#include "P25_InitParam.h"
#include "P25.h"
#include "P25_paramDef.h"
// B_N
#include "LibComSecu.h"
#include "LibEnr_iface.h"
#include "Penr_initParam.h"
// fin B_N    
#include "Pfglc_InitParam.h"
#include "Pasd_InitParam.h"
#include "Pacqima_InitParam.h"
#include "Pio_InitParam.h"
#include "Tra_InitParam.h"
#include "Pcanveh_InitParam.h"
#include "Pcandgo_InitParam.h"
#include "PstarterFcts.h"
#include "if_cp_cs.h"
#include "PstarterComCalcS.h"
#include "Pstartertstmod.h"
#include "Pstarter.h"

// include pour le transfert sur CAN
#include "trfcan_i.h"

/* -------------------------------------------------------------------- */
/* Variables globales de communication									         */
/* -------------------------------------------------------------------- */
Com_BufferReception_s vg_BufferReception;
Com_Message_s vg_MessRecu;
Com_Message_s vg_MessReponse;
Com_Message_s vg_MessEnvoye;

/* -------------------------------------------------------------------- */
/* Parametres de lancement des processus							    */
/* -------------------------------------------------------------------- */
static Pst_ProcDesc vs_DescPacqima =
  { PATH_PACQIMA, PACQIMA_PRIO, 0, 0 };
#ifdef B_N
static Pst_ProcDesc vs_DescPenr =
  { PATH_PENR, PENR_PRIO, 0, 0};
#endif
static Pst_ProcDesc vs_DescPtrace =
  { PATH_PTRACE, PTRACE_PRIO, 0, 0 };
static Pst_ProcDesc vs_DescPcandgo =
  { PATH_PCANDGO, PCANDGO_PRIO, 0, 0 };
static Pst_ProcDesc vs_DescPcanveh =
  { PATH_PCANVEH, PCANVEH_PRIO, 0, 0 };
static Pst_ProcDesc vs_DescPio =
  { PATH_PIO, PIO_PRIO, 0, 0 };
static Pst_ProcDesc vs_DescPfglc =
  { PATH_PFGLC, PFGLC_PRIO, 0, 0 };
static Pst_ProcDesc vs_DescP25 =
  { PATH_P25, P25_PRIO, 0, 0 };
static Pst_ProcDesc vs_DescPasd =
  { PATH_PASD, PASD_PRIO, 0, 0 };

/* -------------------------------------------------------------------- */
/* Declaration Parametres applicatifs								    */
/* -------------------------------------------------------------------- */
static Pacqima_InitParam_s vs_ParamAcqima;
static Tra_InitParam_s vs_ParamPtrace;
static Pcandgo_InitParam_s vs_ParamPcandgo;
static Pcanveh_InitParam_s vs_ParamPcanveh;
static Pio_InitParam_s vs_ParamPio;
static Pfglc_InitParam_s vs_ParamPfglc;
static P25_InitParam_s vs_ParamP25;
static Pasd_InitParam_s vs_ParamPasd;
#ifdef B_N
static Penr_InitParam_s vs_paramPenr;
#endif
/* --------------------------------------------------------------------- */
/*  Corps du programme													 */
/* --------------------------------------------------------------------- */

int
main(void)
{
#ifdef INTERACTIVITE_CLAVIER
  Dgo_Bool_e vl_Fin = FAUX;
  IT vl_Char;
#endif
  LO vl_Rc;
  CH *z_Arg[PST_NB_MAX_PARAM_LIGNE];
  CH *vl_PtrVarEnviron = NULL;
  IT vl_MqNode;
  pid_t vl_PidPcanDgo;
  pid_t vl_PidPcanVeh;
  t_DS_CANVEH vl_dmdCan;
  pid_t vl_PidPio;
  IT vl_StatusParam;
  US vl_Status;

  Donnes_Fichier vl_File;
  Donnes_Fichier *vl_pFile;
  US vl_comSecu = 0;
#ifdef B_N
  Enr_status_e vl_enr;
  pid_t vl_pidPenr;
#endif
  IT vl_statLoc;
  pid_t vl_pidTemp;
  pid_t vl_pidPasd;
  pid_t vl_pidPfglc;
  pid_t vl_pidP25;
  pid_t vl_pidPtrace;
  Enr_paramBoiteNoire_s vl_paramBoiteNoire;
  Enr_paramBoiteNoire_s *vl_paramBoiteNoire_pt;

  // calibration
  cal_paramCalib_CP_s vl_paramCalibrationCp;
  cal_paramCalib_CS_s vl_paramCalibrationCs;
  cal_erreur_e vl_calErr;

#ifdef ESSAIS_VENT
  UL vl_numSession = 0;
  CH vl_pathdest[255];
  CH vl_pathsrc[255];
#endif

  /* -------------------------------------------------------------------- */
  /* Initialisation                                              			*/
  /* -------------------------------------------------------------------- */
#ifdef __QNXNTO__
  // Initialisation de la librairie mig4nto
  if (mig4nto_init(_NTO_CHF_FIXED_PRIORITY) == -1)
    {
      printf("Pstarter : erreur mig4nto init\n");
      exit(-1);
    }
#endif

  memset(&vl_paramBoiteNoire, 0, sizeof(Enr_paramBoiteNoire_s));
  vl_paramBoiteNoire_pt = &vl_paramBoiteNoire;
  vl_pFile = &vl_File;
  vl_pFile->fp = NULL;
  vl_pFile->St[0] = '\0';

#ifdef B_N  	
  vl_enr = enr_startEtGetParam(vl_paramBoiteNoire_pt);
  if (vl_enr!=ENR_OK)
    {
      printf("Pstarter : ERR enr_startEtGetParam() %d",vl_enr);
      exit(-1);
    }
#endif /* B_N */
  vl_comSecu = ComSecu_initShmem();
  if (vl_comSecu != COMSECU_OK)
    {
      printf("Pstarter : ERR ComSecu_initShmem()");
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_COMSECU_INITSHMEM);
    }

#ifdef SERV_TRACE
  /* -------------------------------------------------------------------- */
  /*  Lancement PTrace													*/
  /* -------------------------------------------------------------------- */

  vl_PtrVarEnviron = getenv("MQ_NODE");
  if (vl_PtrVarEnviron != NULL)
    {
      vl_MqNode = atoi(vl_PtrVarEnviron);
      vs_DescPtrace.Node = (nid_t) vl_MqNode;
    }
  else
    {
      printf("Pstarter : Démarrage du serveur de trace en local\n");
    }
  z_Arg[0] = vs_DescPtrace.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = TRA_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamPtrace;
  vg_MessEnvoye.Taille = sizeof(Tra_InitParam_s);
  vl_Rc = SpawnAndSendParam(&vs_DescPtrace, z_Arg, &vg_MessEnvoye,
      vg_BufferReception, &vg_MessRecu);
  if (vl_Rc != DGO_OK)
    {
      printf("Starter : Erreur SpawnAndSendParam Ptrace\n");
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_SPAWN_PTRACE);
    }
  else
    {
      if (vg_MessRecu.Type != TRA_INIT_STATUS)
        {
          printf("Starter : Erreur Type Mess Acquittement Init Ptrace\n");
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PTRACE);
        }
      else
        {
          if (((Tra_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              printf("Starter : Acquittement Init Ptrace negatif\n");
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PTRACE);
            }
        }
    }
  vl_pidPtrace = vg_MessRecu.Processus;
#endif
  printf("Ptrace : lance\n");
  TRA_INIT();
#ifdef SERV_TRACE
  TRA_PUT(4,("Pstarter : Ptrace lance: "));
#endif
  // récupération du niveau de trace

  /* -------------------------------------------------------------------- */
  /* Initialisation des parametres applicatifs							*/
  /* -------------------------------------------------------------------- */
  vl_StatusParam = UP_InitParam(UP_FICHIER_PARA_REGLAGES);
  vl_StatusParam = UP_InitParam(UP_FICHIER_PARA_PHYSIQUES);
#ifndef NEW_CARD
  Pst_AffectationParamPacqima(&vs_ParamAcqima);
#endif
  Pst_AffectationParamP25(&vs_ParamP25);
  Pst_AffectationParamPfglc(&vs_ParamPfglc);
  Pst_AffectationParamPasd(&vs_ParamPasd);
  UP_FermeParam(UP_FICHIER_PARA_REGLAGES);
  UP_FermeParam(UP_FICHIER_PARA_PHYSIQUES);
#ifdef B_N
  vs_ParamPasd.paramBoiteNoire = vl_paramBoiteNoire;
  vs_paramPenr.paramBoiteNoire = vl_paramBoiteNoire;
#endif    

  /* -------------------------------------------------------------------- */
  /* Initialisation des parametres applicatifs CALIBRES						*/
  /* -------------------------------------------------------------------- */
  // lecture des parametres de calibration
  vl_calErr = cal_lectureFichier(NOM_FICHIER_CAL_CP, CAL_FICHIER_CP,
      &vl_paramCalibrationCp);
  if (vl_calErr != CAL_OK)
    {
      TRA_PUT(9,("Pstarter : Erreur de lecture du fichier de calibration %d\n",vl_calErr));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_LECT_FICH_CALIB1);
    }
  vl_calErr = cal_lectureFichier(NOM_FICHIER_CAL_CS, CAL_FICHIER_CS,
      &vl_paramCalibrationCs);
  if (vl_calErr != CAL_OK)
    {
      TRA_PUT(9,("Pstarter : Erreur de lecture du fichier de calibration %d\n",vl_calErr));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_LECT_FICH_CALIB2);
    }
  if (vl_paramCalibrationCp.gyro1.flag == CAL_VALIDE)
    {
      vs_ParamPfglc.paramPhyPfglc.gainCalibrationGyro
          = vl_paramCalibrationCp.gyro1.valeur;
    }
  else
    {
      TRA_PUT(9,("Pstarter : parametre gyro1 non calibre"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_PARAM_GYRO1);
    }
  if (vl_paramCalibrationCp.lacet.flag == CAL_VALIDE)
    {
      vs_ParamP25.paramPhyEpv.prmsVehic.lacetCamera
          = vl_paramCalibrationCp.lacet.valeur;
    }
  else
    {
      TRA_PUT(9,("Pstarter : parametre lacet non calibre"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_PARAM_LACET);
    }
  if (vl_paramCalibrationCp.inclinaison.flag == CAL_VALIDE)
    {
      vs_ParamP25.paramPhyEpv.prmsVehic.inclinaisonCamera
          = vl_paramCalibrationCp.inclinaison.valeur;
    }
  else
    {
      TRA_PUT(9,("Pstarter : parametre inclinaison non calibre"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_PARAM_INCLINAISON);
    }
  if (vl_paramCalibrationCp.ecart.flag == CAL_VALIDE)
    {
      vs_ParamP25.paramPhyEpv.prmsVehic.ecartCamera
          = vl_paramCalibrationCp.ecart.valeur;
    }
  else
    {
      TRA_PUT(9,("Pstarter : parametre ecart non calibre"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_PARAM_ECART);
    }
  if (vl_paramCalibrationCp.CV.flag == CAL_VALIDE)
    {
    }
  else
    {
      TRA_PUT(9,("Pstarter : parametre CV non calibre"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_PARAM_CV);
    }
  if (vl_paramCalibrationCp.CLP.flag == CAL_VALIDE)
    {
    }
  else
    {
      TRA_PUT(9,("Pstarter : parametre CLP non calibre"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_PARAM_CLP);
    }
  if (vl_paramCalibrationCp.cartes.flag == CAL_VALIDE)
    {
    }
  else
    {
      TRA_PUT(9,("Pstarter : parametre cartes non calibre"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_PARAM_CARTES);
    }

  vs_ParamP25.paramPhyEpv.prmsCam.numeroSerieCamera
      = vl_paramCalibrationCp.numero_serie_camera;
#ifdef ENR_VIT_EVOL1
#ifdef B_N
  vs_paramPenr.paramBoiteNoire.numCamera = vl_paramCalibrationCp.numero_serie_camera;
  vs_paramPenr.paramBoiteNoire.numDgo = vl_paramCalibrationCp.numero_serie_boitier;
#endif //B_N 
  vs_ParamPasd.paramBoiteNoire.numCamera = vl_paramCalibrationCp.numero_serie_camera;
  vs_ParamPasd.paramBoiteNoire.numDgo = vl_paramCalibrationCp.numero_serie_boitier;
  vl_paramBoiteNoire.numCamera = vl_paramCalibrationCp.numero_serie_camera;
  vl_paramBoiteNoire.numDgo = vl_paramCalibrationCp.numero_serie_boitier;
#endif //#ifdef ENR_VIT_EVOL1
#ifdef B_N
  // --------------------------------------------------------------------
  // Lancement Penr
  // --------------------------------------------------------------------

  z_Arg[0] = vs_DescPenr.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = PENR_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_paramPenr;
  vg_MessEnvoye.Taille = sizeof(Penr_InitParam_s);
  vl_Rc = SpawnAndSendParam( &vs_DescPenr,
      z_Arg,
      &vg_MessEnvoye,
      vg_BufferReception,
      &vg_MessRecu);
  if (vl_Rc!=DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam Penr\n"));
      Pst_erreur(vl_paramBoiteNoire_pt,PST_ERR_SPAWN_PENR);
    }
  else
    {
      if (vg_MessRecu.Type!=PENR_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Erreur Type Mess Acquittement Init Penr\n"));
          Pst_erreur(vl_paramBoiteNoire_pt,PST_ERR_ACQ_PENR);
        }
      else
        {
          if (((Penr_InitStatus_s*)vg_MessRecu.PtrData)->Status!=DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init Penr negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt,PST_ERR_ACQ_PENR);
            }
        }
    }
  vl_pidPenr = vg_MessRecu.Processus;
  TRA_PUT(4,("Pstarter : Penr lance"));
#endif
  printf("Penr lance\n");

#ifdef TESTINITP25
  // --------------------------------------------------------------------
  // Lancement P25
  // --------------------------------------------------------------------
  z_Arg[0] = vs_DescP25.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = P25_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamP25;
  vg_MessEnvoye.Taille = sizeof(P25_InitParam_s);
  vl_Rc = SpawnAndSendParam( &vs_DescP25,
      z_Arg,
      &vg_MessEnvoye,
      vg_BufferReception,
      &vg_MessRecu);
  if (vl_Rc!=DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam P25\n"));
      Pst_erreur(vl_paramBoiteNoire_pt,PST_ERR_SPAWN_P25);
    }
  else
    {
      if (vg_MessRecu.Type!=P25_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Type Mess Acquittement Init P25\n"));
          Pst_erreur(vl_paramBoiteNoire_pt,PST_ERR_ACQ_P25);
        }
      else
        {
          if (((P25_InitStatus_s*)vg_MessRecu.PtrData)->Status!=DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init P25 negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt,PST_ERR_ACQ_P25);
            }
        }
    }
#endif

  // --------------------------------------------------------------------
  // Lancement Pio
  // --------------------------------------------------------------------

  z_Arg[0] = vs_DescPio.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = PIO_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamPio;
  vg_MessEnvoye.Taille = sizeof(Pio_InitParam_s);
  vl_Rc = SpawnAndSendParam(&vs_DescPio, z_Arg, &vg_MessEnvoye,
      vg_BufferReception, &vg_MessRecu);
  if (vl_Rc != DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam Pio\n"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_SPAWN_PIO);
    }
  else
    {
      if (vg_MessRecu.Type != PIO_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Erreur Type Mess Acquittement Init Pio\n"));
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PIO);
        }
      else
        {
          if (((Pio_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init Pio negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PIO);
            }
        }
    }

  // --------------------------------------------------------------------
  vl_PidPio = vg_MessRecu.Processus;
  TRA_PUT(4,("Pstarter : Pio lance"));
  printf("Pio lance\n");

  // --------------------------------------------------------------------
  // Lancement Pcandgo
  // --------------------------------------------------------------------

  z_Arg[0] = vs_DescPcandgo.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = PCANDGO_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamPcandgo;
  vg_MessEnvoye.Taille = sizeof(Pcandgo_InitParam_s);
  vl_Rc = SpawnAndSendParam(&vs_DescPcandgo, z_Arg, &vg_MessEnvoye,
      vg_BufferReception, &vg_MessRecu);
  if (vl_Rc != DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam Pcandgo\n"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_SPAWN_PCANDGO);
    }
  else
    {
      if (vg_MessRecu.Type != PCANDGO_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Erreur Type Mess Acquittement Init Pcandgo\n"));
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PCANDGO);
        }
      else
        {
          if (((Pac_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init Pcandgo negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PCANDGO);
            }
        }
    }

  vl_PidPcanDgo = vg_MessRecu.Processus;
  // --------------------------------------------------------------------
  TRA_PUT(4,("Pstarter : Pcandgo lance"));
  printf("pcandgo lance\n");

  vl_Status = Pst_CanDgoInitChip(vl_PidPcanDgo);
  if (vl_Status != PST_OK)
    {
      TRA_PUT(9,("Starter : ERR Pst_CanDgoInitChip"));
      Pst_erreur(vl_paramBoiteNoire_pt, vl_Status);
    }

  vl_Status = Pst_CanDgoInitMessCodeur(vl_PidPcanDgo);
  if (vl_Status != PST_OK)
    {
      TRA_PUT(9,("Starter : ERR Pst_CanDgoInitMessCodeur"));

    }

  vl_Status = Pst_CanDgoStartChip(vl_PidPcanDgo);
  if (vl_Status != PST_OK)
    {
      TRA_PUT(9,("Starter : ERR Pst_CanDgoStartChip"));
      Pst_erreur(vl_paramBoiteNoire_pt, vl_Status);
    }

  // --------------------------------------------------------------------
  // Lancement Pacqima
  // --------------------------------------------------------------------

  z_Arg[0] = vs_DescPacqima.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = PACQIMA_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamAcqima;
  vg_MessEnvoye.Taille = sizeof(Pacqima_InitParam_s);
  vl_Rc = SpawnAndSendParam(&vs_DescPacqima, z_Arg, &vg_MessEnvoye,
      vg_BufferReception, &vg_MessRecu);
  if (vl_Rc != DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam Pacqima\n"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_SPAWN_PACQIMA);
    }
  else
    {
      if (vg_MessRecu.Type != PACQIMA_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Erreur Type Mess Acquittement Init Pacqima\n"));
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PACQIMA);
        }
      else
        {
          if (((Pac_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init Pacqima negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PACQIMA);
            }
        }
    }

  TRA_PUT(4,("Pstarter : Pacqima lance niveau 3"));
  printf("pacqima lance\n");
  // --------------------------------------------------------------------
  // Lancement Pcanveh
  // --------------------------------------------------------------------
  z_Arg[0] = vs_DescPcanveh.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = PCANVEH_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamPcanveh;
  vg_MessEnvoye.Taille = sizeof(Pcanveh_InitParam_s);
  vl_Rc = SpawnAndSendParam(&vs_DescPcanveh, z_Arg, &vg_MessEnvoye,
      vg_BufferReception, &vg_MessRecu);
  if (vl_Rc != DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam Pcanveh\n"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_SPAWN_PCANVEH);
    }
  else
    {
      if (vg_MessRecu.Type != PCANVEH_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Type Mess Acquittement Init Pcanveh\n"));
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PCANVEH);
        }
      else
        {
          if (((Pcanveh_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init Pcanveh negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PCANVEH);
            }
        }
    }
  // --------------------------------------------------------------------
  TRA_PUT(4,("Pstarter : Pcanveh lance"));
  printf("pcanveh lance\n");

  vl_PidPcanVeh = vg_MessRecu.Processus;
  vl_Status = Pst_SequenceInitCanVeh(vl_PidPcanVeh);
  if (vl_Status != PST_OK)
    {
      Pst_erreur(vl_paramBoiteNoire_pt, vl_Status);
    }

  // --------------------------------------------------------------------
  // Lancement Pfglc
  // --------------------------------------------------------------------
  z_Arg[0] = vs_DescPfglc.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = PFGLC_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamPfglc;
  vg_MessEnvoye.Taille = sizeof(Pfglc_InitParam_s);
  vl_Rc = SpawnAndSendParam(&vs_DescPfglc, z_Arg, &vg_MessEnvoye,
      vg_BufferReception, &vg_MessRecu);
  if (vl_Rc != DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam Pfglc\n"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_SPAWN_PFGLC);
    }
  else
    {
      if (vg_MessRecu.Type != PFGLC_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Type Mess Acquittement Init Pfglc\n"));
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PFGLC);
        }
      else
        {
          if (((Pfglc_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init Pfglc negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PFGLC);
            }
        }
    }

  // --------------------------------------------------------------------
  TRA_PUT(4,("Pstarter : Pfglc lance"));
  vl_pidPfglc = vg_MessRecu.Processus;
  printf("pfglc lance\n");
  // --------------------------------------------------------------------
  // Lancement P25
  // --------------------------------------------------------------------
  z_Arg[0] = vs_DescP25.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = P25_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamP25;
  vg_MessEnvoye.Taille = sizeof(P25_InitParam_s);
  vl_Rc = SpawnAndSendParam(&vs_DescP25, z_Arg, &vg_MessEnvoye,
      vg_BufferReception, &vg_MessRecu);
  if (vl_Rc != DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam P25\n"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_SPAWN_P25);
    }
  else
    {
      if (vg_MessRecu.Type != P25_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Type Mess Acquittement Init P25\n"));
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_P25);
        }
      else
        {
          if (((P25_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init P25 negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_P25);
            }
        }
    }

  // --------------------------------------------------------------------

  TRA_PUT(4,("Pstarter : P25 lance"));
  vl_pidP25 = vg_MessRecu.Processus;
  printf("p25 lance\n");
  // --------------------------------------------------------------------
  // Attente acquittemnt du passage dans l'etat reply-bloque de p25
  // --------------------------------------------------------------------
  TRA_PUT(4,("Pstarter : Attente 2eme Acq de Pfglc"));

  if (Com_WaitMess(vg_BufferReception, &vg_MessRecu) == COM_OK)
    {
      TRA_PUT(5,("Pstarter : Pfglc reply-bloque"));
      if (vg_MessRecu.Type != PFGLC_INIT_STATUS2)
        {
          TRA_PUT(9,("Starter : Erreur Type Mess Acquittement Init2 PFGLC\n"));
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ2_PFGLC);
        }
      else
        {
          if (((Pfglc_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init 2 Pfglc negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ2_PFGLC);
            }
          else
            {
              vg_MessReponse.Processus = vg_MessRecu.Processus;
              vg_MessReponse.Type = REP_MESS_SYNCHRO;
              vg_MessReponse.PtrData = NULL;
              vg_MessReponse.Taille = 0;
              if (Com_ReplyMess(&vg_MessReponse) != 0)
                TRA_PUT(9,("Starter : erreur reponse acq PFGLC\n"));
            }
        }
    }
  else
    {
      TRA_PUT(9,("Starter : Erreur Com_WaitMess"));
    }

  //---- demarrage CLP
  vl_Status = Pst_DemarrageCLP(vl_PidPcanDgo);
  if (vl_Status != PST_OK)
    {
      TRA_PUT(9,("Pstarter : ERR Pst_DemarrageCLP"));
      Pst_erreur(vl_paramBoiteNoire_pt, vl_Status);
    }
  // --------------------------------------------------------------------
  // Lancement Pasd
  // --------------------------------------------------------------------
  z_Arg[0] = vs_DescPasd.Path;
  z_Arg[1] = NULL;
  vg_MessEnvoye.Type = PASD_INIT_PARAM;
  vg_MessEnvoye.PtrData = &vs_ParamPasd;
  vg_MessEnvoye.Taille = sizeof(Pasd_InitParam_s);
  vl_Rc = SpawnAndSendParam(&vs_DescPasd, z_Arg, &vg_MessEnvoye,
      vg_BufferReception, &vg_MessRecu);
  if (vl_Rc != DGO_OK)
    {
      TRA_PUT(9,("Starter : Erreur SpawnAndSendParam Pasd\n"));
      Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_SPAWN_PASD);
    }
  else
    {
      if (vg_MessRecu.Type != PASD_INIT_STATUS)
        {
          TRA_PUT(9,("Starter : Type Mess Acquittement Init Pasd\n"));
          Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PASD);
        }
      else
        {
          if (((Pasd_InitStatus_s*) vg_MessRecu.PtrData)->Status != DGO_OK)
            {
              TRA_PUT(9,("Starter : Acquittement Init Pasd negatif\n"));
              Pst_erreur(vl_paramBoiteNoire_pt, PST_ERR_ACQ_PASD);
            }
        }
    }

  vl_pidPasd = vg_MessRecu.Processus;
  // --------------------------------------------------------------------
  printf("pasd lance\n");
  TRA_PUT(4,("Pstarter : Pasd lance"));
  TRA_PUT(4,("Pstarter : ---------------- FIN LANCEMENT ------------------"));

#ifdef B_N
  // initialisation des Pids en sharemem, pour lagestion de l'erreur
  vl_comSecu = ComSecu_initPids(vl_pidPasd,vl_pidPfglc,vl_pidP25);

#endif /* B_N */

    //---- demarrage CLP
  /*   	vl_Status = Pst_DemarrageCLP(vl_PidPcanDgo);
   if (vl_Status!=PST_OK) {
   TRA_PUT(9,("Pstarter : ERR Pst_DemarrageCLP"));
   Pst_erreur(vl_paramBoiteNoire_pt,vl_Status);
   } */

  //---- demarrage CV
  vl_Status = Pst_DemarrageCV(vl_PidPcanDgo);
  if (vl_Status != PST_OK)
    {
      Pst_erreur(vl_paramBoiteNoire_pt, vl_Status);
    }
 
  // B_N
  /* on attend la fin de Pasd */
  //	sleep(1)
  vl_pidTemp = waitpid(vl_pidPasd, &vl_statLoc, 0);
  if (vl_pidTemp != vl_pidPasd)
    {
      TRA_PUT(9,("PSTARTER : err attente fin Pasd"));
    }

  vl_pidTemp = waitpid(vl_pidP25, &vl_statLoc, 0);
  if (vl_pidTemp != vl_pidP25)
    {
      TRA_PUT(9,("PSTARTER : err attente fin P25"));
    }
#ifdef B_N
  vl_pidTemp = waitpid( vl_pidPenr,
      &vl_statLoc,
      0);
  if (vl_pidTemp!=vl_pidPenr)
    {
      TRA_PUT(9,("PSTARTER : err attente fin Penr"));
    }
#endif

  vl_pidTemp = waitpid(vl_pidPfglc, &vl_statLoc, 0);
  if (vl_pidTemp != vl_pidPfglc)
    {
      TRA_PUT(9,("PSTARTER : err attente fin Pfglc"));
    }

  vl_dmdCan.IDENT = CG_M_EXITDRV;
  vg_MessEnvoye.Processus = vl_PidPcanVeh;
  vg_MessEnvoye.Type = TYPE_DS_CANVEH;
  vg_MessEnvoye.PtrData = &vl_dmdCan;
  vg_MessEnvoye.Taille = sizeof(t_DS_CANVEH);
  vl_Status = Com_SendMessAndWait(&vg_MessEnvoye, vg_BufferReception,
      &vg_MessRecu);
  if (vl_Status != PST_OK)
    {
      TRA_PUT(9,("Pstarter : Erreur send M_EXITDRV"));
    }

  // fin B_N


  Pst_Fin();
  TRA_PUT(10,("PSTARTER : FIN"));
  TRA_PUT_TYPE(20,TRA_FIN,NULL);
  TRA_CLOSE();
#ifdef SERV_TRACE
  vl_pidTemp = waitpid(vl_pidPtrace, &vl_statLoc, 0);
  if (vl_pidTemp != vl_pidPtrace)
    {
      TRA_PUT(9,("PSTARTER : err attente fin Ptrace"));
    }
#endif
  sync();
#ifdef ESSAIS_VENT

  delay(1000);

  vl_numSession = vl_paramBoiteNoire_pt->numSession;
  sprintf(vl_pathdest,"%senr%d/.",PATH_MESURE_VENT,vl_numSession);
  sprintf(vl_pathsrc,"cp -c %s%d/* %s",vl_paramBoiteNoire_pt->pathBase,vl_numSession,vl_pathdest);
  printf(vl_pathsrc);
  system(vl_pathsrc);
  sprintf(vl_pathsrc,"cp -c /enrvit/enr%d/* %s",vl_numSession,vl_pathdest);
  printf("%s\n",vl_pathsrc);
  system(vl_pathsrc);
  sprintf(vl_pathsrc,"mv -f %s/*.mpf %s",PATH_MESURE,vl_pathdest);
  printf("%s\n",vl_pathsrc);
  system(vl_pathsrc);

#endif              

  return 0;
}

Starter’s function to spawn process and send init message :

[code]Dgo_Status_e SpawnAndSendParam( Pst_ProcDesc* i_ProcDesc,
char* i_Arg[],
Com_Message_s* i_ParamInit,
Com_BufferReception_s i_BuffReception,
Com_Message_s* o_AcqInit)
{
pid_t vl_Pid;
Com_Erreur_e vl_Rc;

vl_Pid = qnx_spawn( 0, 
             NULL, 
             i_ProcDesc->Node, 
             i_ProcDesc->Prio,  
             SCHED_FIFO,  
             0,
             i_ProcDesc->Path,
             i_Arg,  
             environ, 
             NULL, 
             -1 );
			 
// environ : var globale à QNX
if( vl_Pid == -1)
{
    printf("pid negatif\n");
    return(DGO_KO);
}

i_ProcDesc->Pid = vl_Pid;
i_ParamInit->Processus = vl_Pid;
vl_Rc = Com_SendMessAndWait(	i_ParamInit,
							i_BuffReception,
							o_AcqInit); 
if (vl_Rc!=COM_OK)
{
	printf("com ko\n");
	 return(DGO_KO);
}

return(DGO_OK);

}
[/code]

Communication library to handle message passing primitives :

Com_Erreur_e  Com_SendMessAndWait(	Com_Message_s* p_MessEmis,
							Com_BufferReception_s p_BuffReception,
							Com_Message_s* p_MessRecu) {
	struct _mxfer_entry z_SendParts[2];
	struct _mxfer_entry z_ReplyParts[2];
	long z_Rc;
	_setmx(	&z_SendParts[0],&(p_MessEmis->Type),TAILLE_TYPE_MESS);
	_setmx(	&z_ReplyParts[0],&(p_MessRecu->Type),TAILLE_TYPE_MESS);
	_setmx(	&z_SendParts[1],p_MessEmis->PtrData,p_MessEmis->Taille);
	_setmx(	&z_ReplyParts[1],p_BuffReception,TAILLE_MAX_MESS);
	z_Rc = Sendmx(	p_MessEmis->Processus,
           			2,
		   			2,
					z_SendParts,
					z_ReplyParts);
	if (z_Rc==-1) {
		return(COM_KO);
		}
	 else {
		p_MessRecu->PtrData = (void*)p_BuffReception;
		p_MessRecu->Processus = p_MessEmis->Processus;
	}
	return(COM_OK);									
}
Com_Erreur_e Com_WaitMess(	Com_BufferReception_s p_BuffReception,
							Com_Message_s* p_MessRecu) {
	struct _mxfer_entry z_ReceiveParts[2];
	pid_t z_Pid;
	_setmx(	&z_ReceiveParts[0],&(p_MessRecu->Type),TAILLE_TYPE_MESS);	
	_setmx(	&z_ReceiveParts[1],p_BuffReception,TAILLE_MAX_MESS);
	z_Pid = Receivemx(	0,
                		2,
						z_ReceiveParts);
	if(z_Pid==-1) {
		return(COM_KO);
		}
	 else {
		p_MessRecu->Processus = z_Pid;
		p_MessRecu->PtrData = (void*)p_BuffReception;
		}
	return(COM_OK);					  
}

After its creation, Process A waits Starter message with :

Bool_e Pasd_receptionMessageStarter(Com_BufferReception_s i_BufferReception,
    Pasd_InitParam_s **o_paramPasd)

{
  Pasd_InitStatus_s vl_RepInit;
  Com_Erreur_e vl_com;
  Com_Message_s vl_MessRecu;

  /****************************
   *           CODE           *
   ****************************/

  vl_RepInit.Status = DGO_KO;

  vl_com = Com_WaitMess(i_BufferReception, &vl_MessRecu);
  if (vl_com != COM_OK)
    {
      vl_RepInit.Status = DGO_KO;
      return (vl_RepInit.Status);
    }
  else
    {
      vl_RepInit.Status = DGO_OK;
    }
  if (vl_MessRecu.Type != PASD_INIT_PARAM)
    {
      TRA_PUT(9,("PASD : Le message d'init n'est pas du bon type"));
      vl_RepInit.Status = DGO_KO;
      return (vl_RepInit.Status);
    }
  else
    {
      *o_paramPasd = (Pasd_InitParam_s*) vl_MessRecu.PtrData;
      vl_RepInit.Status = DGO_OK;
    }

  vg_PstarterNoProc = vl_MessRecu.Processus;

  return (vl_RepInit.Status);
}

I’ve added several print to understand how is going during the boot sequence. One print after “qnx_spawn” (ie. second snippet) which show the pid number, another after “Com_WaitMess” (ie. fourth snippet) which show “wait”, another after Sendmx function to show the status (ie. third snippet) and one after each SpawnAndSendParam to know if the process is launched (ie. first snippet).

Everything works fine until the creation of the last process named “PASD” :

  • Sendmx returns “No such process” error (ESRCH errno)
  • I have the following prints :
    Spawn Pasd with pid=XXXX
    “No such process”
    Pasd is waiting
    Starter pasd error
  • It seems when PASD is created it hasn’t enough time to switch in Receive-blocked state to ack the Starter’s init message.
  • Mig4nto-procmgr receives the message well

Maybe it’s about priority…i don’t really understand what’s the problem because if message-passing didn’t work it will be for all the process at the beginning of boot sequence.

Ade

I have a theory. Message passing is somewhat different in QNX 6. Instead of sending to a pid and getting a pid from Receive(), and replying to that pid, QNX 6 uses chid’s (channel id’s), coid’s (connection id’s) and rids (receive id’s). The mig24 library must be doing a lot of work to make Sendmx, Receivemx and Replymx do what a MsgSend MsgReceive and MsgReply do. My theory is that a bug has crept into 6.5 which no one has come across. I saw something like this creep into Photon a while back that prevented one from using both name_locate and PtTimer in the same program, because both pieces of code were using the same channel.

If this is the case, there is straight forward, if not simple work around. Rewrite your code using QNX 6 message passing primitives. Since you’ve already put wrappers around them, your work should be minimized.

Two things

  1. A bit of a long shot, but have you printed out the pid_t returned from the qnx_spawn() call? Does it match the one for the actual PASD process? pid_t is defined in header files. I’m wondering if QNX changed it’s size from 32 bits (6.3) to 64 bit in 6.5 (you could also print sizeof(pid_t) to find it’s size) or if your internal structure for Pst_ProcDesc is using pid_t as the variable type.

  2. Assuming that #1 isn’t the problem, what happens if you change the order of your spawn process in the main program. Say spawn PASD 2nd last instead of last and move the 2nd last process to last. Your S/W may not execute properly but I’m more interested in knowing if it starts all the processes without any problems.

Tim

Hi Tim,

Sorry for delay…

  1. Pst_ProcDesc uses pid_t structure to stock process’s pid. A sizeof pid_t returns 4 under 6.5 (same as 6.3).
  2. The behaviour is very strange… I’ve modified the main loop of Pasd by a sleep to be able to change the order of the spawn sequence in Starter program. Then i check if i had the same behaviour ie Pasd doesn’t finish its start sequence → ok same behaviour.
    - I’ve moved it before PFGLC spawn → spawn of Pasd is ok, the boot sequence finished well
    - Then I put Pasd before P25 spawn → same result Pasd is ok, boot sequence ok
    - Then Pasd after P25 spawn (just after printf(“P25 lance\n”):wink: → Pasd crashed communication becomes KO → WTF ?

I don’t understand why P25 could create problems with the mig4nto procmanager or with Pasd. P25 does nothing “new” in comparison of the others process (share memory, attach signal and algorithms initialisation) …

No problem on the delay. You must have a very flexible schedule :slight_smile:

So if I understand your findings correctly, everything works fine (ie ALL processes start and communicate correctly) if you place PASD before PFGLC or if you place PASD before P25. But once it’s placed after P25 (make PASD the last item in the list) it doesn’t work.

If that’s the case the solution sounds pretty easy. Just start PASD earlier with the sleep delay. :laughing:

In reality it sounds like there is a subtle bug in P25 that has manifested itself in 6.5. Did you by chance change compilers in 6.5? Many years age we moved from 2.95 to 3.3.5 and found all kinds of subtle bugs and crashes in our code. Everyone was in fact a legitimate bug on our side. But the change of compiler versions exposed them to us.

Otherwise, short of posting your P25 code (assuming it’s not that large) the best thing I can suggest is to start commenting out blocks of code in P25 until PASD works. Once it works, you know which block of code is causing the problem (alternatively maybe pausing P25 in the debugger will be enough to let PASD start so that you can gradually step though P25 until PASD stops working).

Tim

If only i could do this… Haha :slight_smile:

When i move from qnx 6.3 to 6.5.0, the compiler has changed naturally from 2.95 to 4.4.2 in my VM.
Under momentics IDE 4.7, i don’t know how to get the version of gcc, it seems to be 3.3.5.

Let’s look deeper in P25 to understand what’s wrong there…I will do as you suggest by splitting P25’s parts. It may takes some days. In the meantime, thanks.

Ade

PS : i thought that using mig4nto lib would be faster to port this app…haha

Good Luck and Good Hunting.

I doubt the issue is going to be anything to do with mig4nto. It’s almost surely going to be related to changing compilers.

The big things we noticed when switching were that:

  1. Uninitialized variables (in C type code) were treated differently. By that I mean the newer compiler assigned different local variables to be register variables and thus vulnerable to not being initialized.
  2. Stack variables were treated differently. For example we found some local arrays in our code declared as ’ char a[10]’ and a bug in the code was doing loops from 1-10 instead of 0-9 and walking off the end into the stack which wasn’t mangling things in 2.95 but was in 3.3.5. I think this had to do with how chars and shorts were being 4 byte aligned. This alignment is the kind of thing that may affect your shared memory regions depending on what’s stored there and how you copy data into/out of these regions.

Not to scare you too much but you may find that once you fix the start up problem that you encounter lots of other problems once the code runs. You will have to basically regression test everything.

Tim

Hi Tim,

I tried a last thing before to look further in P25 by adding some delay (5ms) between the process creation (qnx_spawn) and the first send of parameters (Com_SendMessAndWait) in SpawnAndSendParam function.
My idea was to be sure that the created process switch to receive blocked state before starter send the message. It could explain why sendmx returns me a “No such process” error.

The fact it’s working with this “dirty” patch…Once all process are started, everything runs well, realtime constraints are respected for the moment. The good point is that delay is only needed during creation and initialisation phase.

If i have time, i’ll port all sources to 6.5 without the mig4nto strap but for now i leave it like this.

Thanks for your time and all your advise !

Ade