Welcome, Guest. Please login or register.

Author Topic: Why doesn't this code starts automatically (full example with ports and message)...Also SAS linking  (Read 3964 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
Ok, I resourt to ask you why this doesn't work.   :-o
This painfully was stripped down from some program I'm doing, or should I say, trying to...

Here's the deal. Two programs, the MainTask and the OtherProcess. MainTask loads and creates the OtherProcess, wich is compiled sperately, from Ram: using CreateNewProc() (or CreateProc() wich older AOS versions). After loading OtherProcess Maintask sets up a message and a port to receive a reply.

The problem is the MainTask simply stops and hangs and I can't close the window. Given the code it should stop print a message and exit if it doesn't find the OtherProcess port. So I take it it finds it? But it just stops and the OtherProcess doesn't even output the initial message.
I managed to make it work like this. Runing the OtherProcess first from workbench(haven't tried from another shell but i guess it should work too) and then running the MainTask.
But in this case two instances of OtherProcess are running right?

So I take it that the MainTask is missing something to make the OtherProcess run. I wanted also know what's missing for it to display the messages in the same Window as the MainTask, cause that's what was intended when I wrote the code.

Here's the code for both, no clean up is included for simplicity, don't bother I just want to know why it doesn't work, my main program has cleanup for this part of the ini process.

MainTask

Code: [Select]

#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <exec/execbase.h>
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/exec.h>
#include <utility/utility.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <stdlib.h>

struct Library *UtilityBase;

struct MsgPort *ReplyPort;
struct MsgPort *OtherProcessPort;

BPTR OtherProcessSegList = 0;

struct Message_to_OtherProcess
  { struct Message MesstoOP;
    struct Task *MainTask;
    struct Task *OtherProcess;
  };

struct Message_to_OtherProcess *Message_to_OtherProcess, *OtherProcessResponse;

struct Task *MainTask; /*This task*/
struct Task *OtherProcess;



int main (int argc, char **argv)
{                
 extern struct ExecBase *SysBase;
 
 char *OtherProcessName = &quot;Ram:OtherProcess&quot;;
 struct MsgPort *OtherProcess35;
 struct Process *OtherProcess;
 BPTR MainTaskOutputHandle;
 
 if (!(Message_to_OtherProcess  = (struct Message_to_OtherProcess *)AllocMem (sizeof(Message_to_OtherProcess),MEMF_PUBLIC|MEMF_CLEAR)))
   {printf (&quot;Couldn't allocate memory for Message to OtherProcess\n&quot;);
    exit (0);}
 
 if (!(ReplyPort =  CreatePort (0,0)))
   {printf (&quot;Couldn't create ReplyPort\n&quot;);
    exit (0);}
 Message_to_OtherProcess->MesstoOP.mn_ReplyPort = ReplyPort;
 
 
 if (!(OtherProcessSegList=LoadSeg(OtherProcessName)))
      {printf (&quot;Couldn't find OtherProcess\n&quot;);
       exit (0);}

 MainTaskOutputHandle = Output();
 
 printf(&quot;Exec Version is %d.%d\n&quot;,SysBase->LibNode.lib_Version,SysBase->LibNode.lib_Revision);
 
 if (SysBase->LibNode.lib_Version<=36)
   
    {if (!(OtherProcess35 = CreateProc(&quot;OtherProcess&quot;, 0L, OtherProcessSegList, 1000L)))
      {printf (&quot;Couldn't find OtherProcess35\n&quot;);
      exit(0);}
    printf (&quot;Loaded OtherProcess35\n&quot;);
    }
 
 /* else Kickstart is >=v36, add OtherProcess using CreateNewProc */
 else
 {
   struct TagItem TagsforCrtNewPr[5];
   
   /*open utility library*/
   if (!(UtilityBase = OpenLibrary (&quot;utility.library&quot;,0L)))
     {printf (&quot;Couldn't open utility.library\n&quot;);
      exit(0);}
     
   TagsforCrtNewPr[0].ti_Tag = NP_Seglist;
   TagsforCrtNewPr[0].ti_Data = OtherProcessSegList;
   TagsforCrtNewPr[1].ti_Tag = NP_Name;
   TagsforCrtNewPr[1].ti_Data = (ULONG)&quot;OtherProcess&quot;;
   TagsforCrtNewPr[2].ti_Tag = NP_Cli;
   TagsforCrtNewPr[2].ti_Data = TRUE;
   TagsforCrtNewPr[3].ti_Tag = NP_Output;
   TagsforCrtNewPr[3].ti_Data = MainTaskOutputHandle;
   TagsforCrtNewPr[4].ti_Tag = TAG_DONE;
   if (!(OtherProcess = CreateNewProc (TagsforCrtNewPr)))
      {printf(&quot;Couldn't find OtherProcess\n&quot;);
      exit(0);}
   printf(&quot;Other Process Loaded Successfully\n&quot;);
 }

 /*Locate MainTask*/
 MainTask = FindTask(NULL);
 Message_to_OtherProcess->MainTask = MainTask;
 
 
 /******************** WAIT FOR OTHER PROCESS TO SET UP IT'S PORT*************************/
 Delay (250);
 
 /*Send message to OtherProcess and wait for reply*/
 
 if (!(OtherProcessPort = FindPort (&quot;OtherProcessPort&quot;)))
   {printf(&quot;Couldn't find OtherProcessPort\n&quot;);
    exit (0);}
 PutMsg (OtherProcessPort, (struct Message *)Message_to_OtherProcess);
 WaitPort (ReplyPort);
 if (!(OtherProcessResponse = (struct Message_to_OtherProcess *)GetMsg (ReplyPort)))
   {printf (&quot;No message at port\n&quot;);
    exit (0);}
 
 printf (&quot;Message from OtherProcess received dude!!!\n&quot;);
 OtherProcess = OtherProcessResponse->OtherProcess;
 
 
/*void CleanUp (void)*/

/* Should have something like that ;) */


exit (0);
}




OtherProcess

Code: [Select]
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include

struct Task *MainTask;
struct Task *OtherProcess; /*This one actually*/

struct MsgPort *OtherProcessPort;

struct Message_to_OtherProcess {
struct Message MesstoOP;
struct Task *MainTask;
struct Task *OtherProcess;
};
struct Message_to_OtherProcess *ReceivedMessage;

int main (int argc, char **argv)
{
 printf("OtherProcess Ver1.0, 2004\n");

 if (!(OtherProcessPort = CreatePort ("OtherProcessPort", 0)))
   {printf ("Couldn't create OtherProcessPort\n");
    exit (0);}
 
 WaitPort (OtherProcessPort);
 if (!(ReceivedMessage = (struct Message_to_OtherProcess *)GetMsg (OtherProcessPort)))
   {printf ("No message received");
    Delay (200UL);
    exit (0);}
 printf ("Message from MainTask received DUDE!!\n");
 MainTask  = ReceivedMessage->MainTask;
 
 
 OtherProcess = FindTask(NULL);
 ReceivedMessage->OtherProcess = OtherProcess;
 
 ReplyMsg ((struct Message *)ReceivedMessage);


 printf ("Message replyed...");

exit (0);
}



And by the way, could someone write a very short idiot's guide to linking with SAS C? I have it complaining about some undefined symbols and I'm pretty sure that the stub it prompts to link with as default could be the cause of some programs crashing (not in the exaple above) :oops:
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
@Sidewinder

" What is the undefined symbol that the linker complains about?"
Some functions on jpeg.library. It's because I'm not giving the right instructions to compile and link I think.

"Usually the easiest way to link is to add "link" to the sc command:
sc myprog.c myprog link"

I'm using a SASC project thingie. I'll try that. After link comes the object to link with right?


\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
@Cymric

"First of all: your code is subject to deadlocks. Yes, I know you incorporated Delay()s to introduce 'sufficient' pause for the ports to appear. But that is a Bad Idea in general. Way better is to start the main program, have it start the second while waiting for a signal from the second program to start the message exchange. That way deadlocks are avoided."

Yes, but the stupid thing is, I'm trying to send a message with a pointer to the main task and it's allocated signal to the child process in the first place  :-) This is because the child process is loaded from disk as a separate compiled program. But I think 250 ticks (5 seconds) should be enouph as I don't have anything else running.
This is just to understand what's wrong with this and learn, I guess I'll have to get another method if I want to do this with 1.3.

"Second, an illegal copy of the RKRF: Libraries informs me you need to set the Message's type and length prior to sending, which you have not done. You need to add the following lines below
Message_to_OtherProcess->MesstoOP.mn_ReplyPort = ReplyPort;
Message_to_OtherProcess->MesstoOP.mn_Node.ln_Type = NT_MESSAGE;
Message_to_OtherProcess->MesstoOP.mn_Length=sizeof(struct Message_to_OtherProcess));"

Yes! I forgot that. Done now, but it still hangs. The child process doesn't even display the initial message on the Shell.


"Third, starting a program from the Workbench involves waiting for the startup message from the Workbench itself. I think the startup code already handles that, and it is also exceedingly unlikely that your code interferes with this special message as the message ports are very different. Nevertheless, I've always paid extra good care when dealing with the Workbench ."

Hmm, ok later:-)

"Finally, I have to admit I found it extremely odd that the return type of CreateProc() is struct Message *. Are you *sure* that it isn't struct Process *?"
It's struct MsgPort actually...

Funny that  the initialization of a program can be much bigger and troublesome than the program itself.
 
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
@Cymric

I stripped down the CreateProc() and CreateNewProc() stuff (see below) and it works flawlessly  :-D So the problem is there.

That flush thing you mentioned I didn't do it because like it is now the OtherProcess simply outputs in it's own window.
Don't have time now, will try to output to the MainTask window later...

So, the hunt to the bug is declared  :-) What was wrong with the first versions ?


Here's the now working versions without CreateProc() and CreateNewProc():

MainTask

Code: [Select]

#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <exec/execbase.h>
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/exec.h>
#include <utility/utility.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <stdio.h>
#include <stdlib.h>


struct MsgPort *ReplyPort;

struct Message_to_OtherProcess
  { struct Message MesstoOP;
    struct Task *MainTask;
    struct Task *OtherProcess;
  };

struct Message_to_OtherProcess *Message_to_OtherProcess, *OtherProcessResponse;

struct Task *MainTask; /*This task*/
struct Task *OtherProcess;



int main (int argc, char **argv)
{                
 
 BPTR MainTaskOutputHandle;
 
 if (!(Message_to_OtherProcess  = (struct Message_to_OtherProcess *)AllocMem (sizeof(Message_to_OtherProcess),MEMF_PUBLIC|MEMF_CLEAR)))
   {printf (&quot;Couldn't allocate memory for Message to OtherProcess\n&quot;);
    exit (0);}
 
 if (!(ReplyPort =  CreatePort (0,0)))
   {printf (&quot;Couldn't create ReplyPort\n&quot;);
    exit (0);}
 Message_to_OtherProcess->MesstoOP.mn_ReplyPort = ReplyPort;
 Message_to_OtherProcess->MesstoOP.mn_Length = sizeof(struct Message_to_OtherProcess);
 Message_to_OtherProcess->MesstoOP.mn_Node.ln_Type = NT_MESSAGE;
   
 
 MainTaskOutputHandle = Output();

 /*Locate MainTask*/
 MainTask = FindTask(NULL);
 Message_to_OtherProcess->MainTask = MainTask;
 
 
 /******************** WAIT FOR OTHER PROCESS TO SET UP IT'S PORT*************************/
 Delay (250);
 
 /*Send message to OtherProcess and wait for reply*/
 
 if (!(OtherProcessPort = FindPort (&quot;OtherProcessPort&quot;)))
   {printf(&quot;Couldn't find OtherProcessPort\n&quot;);
    exit (0);}
 PutMsg (OtherProcessPort, (struct Message *)Message_to_OtherProcess);
 WaitPort (ReplyPort);
 if (!(OtherProcessResponse = (struct Message_to_OtherProcess *)GetMsg (ReplyPort)))
   {printf (&quot;No message at port\n&quot;);
    exit (0);}
 
 printf (&quot;Message from OtherProcess received dude!!!\n&quot;);
 OtherProcess = OtherProcessResponse->OtherProcess;
 
 
/*void CleanUp (void)*/

/* Should have something like that ;) */


exit (0);
}



OtherProcess

Code: [Select]
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include

struct Task *MainTask;
struct Task *OtherProcess; /*This one actually*/

struct MsgPort *OtherProcessPort;

struct Message_to_OtherProcess {
struct Message MesstoOP;
struct Task *MainTask;
struct Task *OtherProcess;
};
struct Message_to_OtherProcess *ReceivedMessage;

int main (int argc, char **argv)
{
 printf("OtherProcess Ver1.0, 2004\n");

 if (!(OtherProcessPort = CreatePort ("OtherProcessPort", 0)))
   {printf ("Couldn't create OtherProcessPort\n");
    exit (0);}
 
 WaitPort (OtherProcessPort);
 if (!(ReceivedMessage = (struct Message_to_OtherProcess *)GetMsg (OtherProcessPort)))
   {printf ("No message received");
    Delay (200UL);
    exit (0);}
 printf ("Message from MainTask received DUDE!!\n");
 MainTask  = ReceivedMessage->MainTask;
 
 
 OtherProcess = FindTask(NULL);
 ReceivedMessage->OtherProcess = OtherProcess;
 
 ReplyMsg ((struct Message *)ReceivedMessage);


 printf ("Message replyed...");

exit (0);
}
 
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
@Sidewinder
Cool.
What about when you want to link with and external link library?
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
Ok, I'm back... Tried it with that NP_CloseOutput tag written as FALSE. It's better, now sometimes it crashes when I load it first time, others it works well and the OtherProcess now outputs well to the MainTask window :-)
One of the problems could be that I donn't have any cleanup deleting the MsgPorts so when I run it second time the port list is corrupt.
But still that doesn't justify the fact it randomly crashes even when run first time after a cold boot.
I remember in the RKM Lib they say that one should do a Forbid()before calling the FindPort(), but in this case I know the port is not going anywhere...
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
Hey 8-) Went straight to c) and SAS/C does allow debbuging for subtasks and processes but I haven't read the manual in that part. Over 100 pages just for the debugger. Very complete package.

Anyway, done a step by step trace through each function and it crashes right when I call the CreateNewProc function so the problem is there, I just can't see what it is. Could it be the NP_Cli Tag ? I don't have the DOS manual... The includes say that tag is for creating a cli structure.

I'm gonna go the lazy way and wait for someone to give a hint, already tired, I'm sure I won't forget the error when I know what it is
 :-o
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
By the way, it's not the NP_Cli tag either. I though that could be causig the NewProcess startup to treat it like a Cli process and not remove the WBStartup message before using the DOS library functions. But it still crashes when launched from WB :pissed:
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
Found the {bleep}!! :-x

It's in this line:

Code: [Select]
if (!(Message_to_OtherProcess  = (struct Message_to_OtherProcess *)AllocMem (sizeof(Message_to_OtherProcess),MEMF_PUBLIC|MEMF_CLEAR)))
 
I guess it should be obvious. Do I look stupid now? 8-)
But I guess it's with errors like these that one learns.

I can now go on with the other stuff  :-D
\\"We made Amiga, they {bleep}ed it up\\"