Login
Username:

Password:

Remember me



Lost Password?

Register now!

Sections

Who's Online
101 user(s) are online (50 user(s) are browsing Forums)

Members: 1
Guests: 100

Georg, more...

Headlines

Forum Index


Board index » All Posts (colinw)




Re: OS4.1 bugs
Just popping in
Just popping in


@Chris

Besides the fact that every one of those functions actually has a return code, there is no checking being done.
Also, the 'posn' variable is supposed to be signed.

However, semantics aside, you did actually find an issue with OFFSET_CURRENT with JXFS filesystem, the fix will be in the update due out shortly.

Thanks for finding that.

Go to top


Re: Subscribing to file system notifications
Just popping in
Just popping in


@abalaban
Yes, go ahead....

Go to top


Re: How do you set a "stack cookie?"
Just popping in
Just popping in


@rwo

Yes, DOS uses it in RunCommand().
Workbench uses it too, and also the shell handler.

See; IDOS->FindSegmentStackSize() function.

Go to top


Re: How do you set a "stack cookie?"
Just popping in
Just popping in


@Rigo

Just use the USED define in amiga-compiler.h which is
automatically included.

static USED const char *stack = "$STACK:65535";

Go to top


Re: Check existence of assign
Just popping in
Just popping in


@BillE

APTR oldwin = IDOS->SetProcWindow((APTR)-1);
BPTR lock = IDOS->Lock(assign_name,SHARED_LOCK);
IDOS->UnLock(lock); /* 0 safe */
IDOS->SetProcWindow(oldwin);

if( lock )
{
IDOS->Printf("%s exists\n",assign_name);
}
else
{
IDOS->Printf("%s does not exist\n",assign_name);
}

Go to top


Re: Subscribing to file system notifications
Just popping in
Just popping in


@orgin
Here's the source code for a test program I used for the DOS notify handler.
It's a bit messy, but i'm too-lazy to tidy it up.
Compile it as is (with -nostdlib) and you will see all three methods at work.

Start it from a shell with one argument that is the path to the filesystem object to be monitored.

=====================================================



#define __NOLIBBASE__
#define __NOGLOBALIFACE__
#include <proto/exec.h>
#include <proto/dos.h>

#include <dos/startup.h>

/****************************************************************************/ 

struct CustomHook 
{
 
struct Hook       H;  /* must be first */
 
struct ExecIFace *IExec;
 
struct DOSIFace  *IDOS;
 
BPTR              Output;
 
ULONG             Line;
};

TEXT *actions[] = 
{
 
"NHM_ACTION_INITIAL",
 
"NHM_ACTION_ADD",
 
"NHM_ACTION_CHANGE",
 
"NHM_ACTION_DELETE",
 
NULL
};

/****************************************************************************/

STATIC LONG HookFuncstruct CustomHook *hookAPTR resv UNUSEDstruct NotifyHookMsg *msg )
{
 
LONG indx msg->nhm_Action;

 
indx ++;  /* starts at -1 */
 
indx &= 3;
 
 
hook->IDOS->FPrintf(hook->Output,"%04lu HOOK Ping; '%s'  [%s]\n"
     
hook->Line++, msg->nhm_Nameactions[indx]);

 return(
0);
}

/****************************************************************************/

STATIC LONG mmainstruct ExecIFace *IExecstruct DOSIFace IDOS )
{    
 
TEXT namebuf[256];
 
struct NotifyRequest *nr_hook NULL;
 
struct NotifyRequest *nr_sig NULL;
 
struct NotifyRequest *nr_msg NULL;
 
struct MsgPort *mport NULL;
 
struct CustomHook HK;
 
LONG   numnotify =0;
 
LONG   ok 0;
 
STRPTR args;


 
IDOS->ReadItem(namebuf,sizeof(namebuf),NULL);
 
args namebuf;

 
 if( *
args <= 32 )
 {
  
args "RAM:";
 }
 
 if( 
'?' == *args )
 {
  
IDOS->PutStr("USAGE:    Notify  <file/directory> \nIf not specified, defaults to RAM:\n\n");
  return(
RETURN_FAIL);
 }







/***************  HOOK  **************/
 
HK.H.h_Entry = (APTR) &HookFunc;
 
HK.IExec     IExec;
 
HK.IDOS      IDOS;
 
HK.Output    IDOS->Output();
 
numnotify  ++;

 
nr_hook IDOS->AllocDosObjectTagsDOS_NOTIFYREQUEST
   
ADO_NotifyNameargs,
   
ADO_NotifyMethodNRF_CALL_HOOK,
   
ADO_DOSMethodOnly,TRUE,
   
ADO_NotifyInitialTRUE,
   
ADO_NotifyHook, &HK,
   
TAG_DONE );

 if( 
nr_hook )
 {
    if( 
IDOS->StartNotifynr_hook ) )
  {
//   IDOS->Printf("DOS HOOK Notification started for '%s' as '%s'\n", nr_hook->nr_Name, nr_hook->nr_FullName);
   
ok ++;
  }
  else
  {
   
IDOS->Printf("DOS HOOK Notification FAILED because; %m\n"0);
  }
 }
 else
 {
  
IDOS->Printf("ADO(DOS_NOTIFYREQUEST,HOOK) FAILED because; %m \n",0);
 }





/***************  SIGNAL  **************/
 
numnotify ++;
 
nr_sig IDOS->AllocDosObjectTagsDOS_NOTIFYREQUEST
   
ADO_NotifyNameargs,
   
ADO_NotifyMethodNRF_SEND_SIGNAL,
   
ADO_DOSMethodOnly,TRUE,
   
ADO_NotifyTaskIExec->FindTask(NULL),
   
ADO_NotifySignalNumberSIGBREAKB_CTRL_F,
   
ADO_NotifyInitialTRUE,
   
TAG_DONE );

 if( 
nr_sig )
 {
    if( 
IDOS->StartNotifynr_sig ) )
  {
//   IDOS->Printf("DOS SIGNAL Notification started for '%s' as '%s'\n", nr_sig->nr_Name, nr_sig->nr_FullName);
   
ok ++;
  }
  else
  {
   
IDOS->Printf("DOS SIGNAL Notification FAILED because; %m\n"0);
  }
 }
 else
 {
  
IDOS->Printf("ADO(DOS_NOTIFYREQUEST,SIGNAL) FAILED because; %m \n",0);
 }







/***************  MESSAGE  **************/
 
numnotify ++;
 if(( 
mport IExec->CreateMsgPort() ))
 {

  
nr_msg IDOS->AllocDosObjectTagsDOS_NOTIFYREQUEST
   
ADO_NotifyNameargs,
   
ADO_NotifyMethodNRF_SEND_MESSAGE,
   
ADO_DOSMethodOnly,TRUE,
   
ADO_NotifyPortmport,
   
ADO_NotifyInitialTRUE,
   
TAG_DONE );

  if( 
nr_msg )
  {
     if( 
IDOS->StartNotifynr_msg ) )
   {
//    IDOS->Printf("DOS MESSAGE Notification started for '%s' as '%s'\n", nr_msg->nr_Name, nr_msg->nr_FullName);
    
ok ++;
   }
   else
   {
    
IDOS->Printf("DOS MESSAGE Notification FAILED because; %m\n"0);
   }
  }
  else
  {
   
IDOS->Printf("ADO(DOS_NOTIFYREQUEST,MESSAGE) FAILED because; %m \n",0);
  }

 }



//leave:
 
if( numnotify == ok )
 {
  
ULONG signalportmask=0;
  
struct Message *msg NULL;


  
HK.Line 1;


  
IDOS->PutStr("Ready:  ^C to exit.......\n");

  if( 
mport )
  {
   
portmask 1UL << mport->mp_SigBit;
  }

  do
  {
//   IDOS->PutStr("\n");

   
signal IExec->WaitSIGBREAKF_CTRL_C SIGBREAKF_CTRL_F portmask );


   if( 
signal SIGBREAKF_CTRL_F )
   {
    
IDOS->Printf("%04lu SIGNAL Ping; '%s'\n"HK.Line++, nr_sig->nr_FullName);
   }

   if( 
signal portmask )
   {
    
IDOS->Printf("%04lu MESSAGE Ping; '%s'\n"HK.Line++, nr_sig->nr_FullName);

    while(( 
msg IExec->GetMsg(mport) ))
    {
     
IDOS->PutStr(" -- MESSAGE_REPLIED\n\n");

     
IExec->ReplyMsg(msg);
    }
   }

  }
  while( ! (
signal SIGBREAKF_CTRL_C)); 

  
IDOS->PutStr("\nProgram Exit.....\n\n");
 
 }


 
IDOS->EndNotifynr_hook );
 
IDOS->FreeDosObjectDOS_NOTIFYREQUESTnr_hook );

 
IDOS->EndNotifynr_sig );
 
IDOS->FreeDosObjectDOS_NOTIFYREQUESTnr_sig );

 
IDOS->EndNotifynr_msg );
 
IDOS->FreeDosObjectDOS_NOTIFYREQUESTnr_msg );


 if( 
mport )
 {
  
IExec->DeleteMsgPort(mport);
 }

    return(
RETURN_OK);
}


/****************************************************************************/

LONG _start(STRPTR args UNUSEDLONG arglen UNUSEDstruct ExecBase *SysBase)
{
    
struct ExecIFace *IExec = (struct ExecIFace *)SysBase->MainInterface;
    
struct Library *DOSBase = (struct Library *)IExec->OpenLibrary(DOSNAME50);
    
long rc RETURN_ERROR;

    if (
DOSBase)
    {
        
struct DOSIFace *IDOS = (struct DOSIFace *)IExec->GetInterface(DOSBase"main"1NULL);

        if (
IDOS)
        {
            
rc mmain(IExecIDOS);

            
IExec->DropInterface((struct Interface *)IDOS);
        }

        
IExec->CloseLibrary(DOSBase);
    }

    return( 
rc );
}

/****************************************************************************/

TEXT USED vers[] = "\0$VER: It's just a test program, Dammit !!, 52.1 (28.12.2007)\n\r";


/****************************************************************************/
/* EOF */

=====================================================


Edit: Added code tags


Edited by orgin on 2009/3/21 17:35:34
Edited by colinw on 2009/3/22 12:35:29
Go to top


Re: Lock() problem
Just popping in
Just popping in


@orgin

Oops !! - Fixed now.

Hmmm, why it took all this time for someone to spot that one. (":/

Go to top


Re: Lock() problem
Just popping in
Just popping in


@orgin

Just spotted something.....

The FreeDosObject() of the data block from ExamineDir()
is not appropriate in your PathTypeFallback() function.

The data blocks are allocated from a memory pool and
stored in the internal list and the whole lot is freed
when you call ReleaseDirContext().

However, as you are not looping here, you'd probably never
know anything was up.

Because ExamineDir() uses a memory pool and can reuse
the nodes on subsequent calls, if you were looping,
you'd likely be visited by the reaper for putting
it back into the pool but leaving it still in the list
without calling IExec->Remove() first.
However, seeing you only call ExamineDir() once, you got away with it.


Only ExamineObject() requires you free the data blocks individually when you're done with it.


I've just updated the autodocs to make this point much clearer.

Go to top


Re: Lock() problem
Just popping in
Just popping in


@orgin

The issue is that an exclusive lock implies that it is exclusive, and that means no-one else is allowed to futz-around with it.

The best you can do is get a listing of it with a directory scan of the parent directory if you do not have access to the original lock itself.

The filesystem is serious about exclusivity, and if it's not your lock, you're out of luck trying to force access from another client.

The fact that you have limited access to these is by design and not actually a fault.

BTW:
You really should first attempt a normal ExamineObject() with the string name before falling through to this fallback
method of scanning this entire directory, only if you hit a ERROR_OBJECT_IN_USE error, it will be a hell of a lot faster.

Go to top


Re: Lock() problem
Just popping in
Just popping in


@colinw

PS:
The EX_FileHandleInput also works the same way as locks
when using Examineobject().

Go to top


Re: Lock() problem
Just popping in
Just popping in


@orgin
// @ToDo: Should probably parse EX_MatchString before using it, even without wildcards


I'll say, it will blow up in your face later if you don't.

Go to top


Re: Lock() problem
Just popping in
Just popping in


@orgin

You cannot second Lock() and exclusive lock.

If you read the docs for ExamineObject() you will
see that passing a string name implies a Lock().
That's why it fails.

If you already have the exclusive lock, just call
ExamineObject() with EX_FileLockInput, that will
work on exclusive locks as it is passed to the filesystem directly.

If you want to know the parent directory of the exclusive lock, then call ParentDir() of the exclusive lock,
and don't forget to unlock what ParentDir() returns.

Go to top


Re: LockDosList() troubles
Just popping in
Just popping in


Firstly, you MUST NEVER perform any filesystem operations while you have
the doslist locked, as it will most likely end in a deadlock if your
action causes a handler startup or other action that changes the doslist.

Calling any DOS functions is also unwise for that matter as they may take
an innordinant amount of time to complete, and as of V53 the doslist
lock still implies a Forbid(), which means that multitasking stops.

Better to do it this way;
Make a struct MinList, call NewMinList() on it.
Lock the doslist, use the flags; LDF_DEVICES|LDF_VOLUMES|LDF_READ.

Itterate, for each entry returned, allocate a minnode structure that
holds the relevant data you want, namely dol_Type, dol_Port and some
space for the dol_Name string. Something like this will do;

struct MyNode
{
struct MinNode my_Node; /* a simple struct Node */
int32 my_Type; /* holds the dol_Type DLT_xxx value */
struct MsgPort *my_Port; /* ptr to handler process port */
TEXT my_Name[256]; /* A C-String buffer for the BSTR name */
};

Then allocate one of these each time as sizeof(MyNode), and copy out
the relevant fields. Then IExec->AddTail() the node to your minlist.
Do this until you fall out, then unlock the doslist ASAP.

Now, if a DLT_VOLUME node has the same port address as a DLT_DEVICE,
then you have found the matching nodes for a given mounted volume.

Just one caveat, DON'T actually use the port for anything other than
the comparison, as a volume can "go away" at any moment.

Also, don't forget to IExec->RemHead() all your nodes and free them
when you're finished..

Go to top


Re: Wanted Ctorrent Betatester[V2.00 out]
Just popping in
Just popping in


@Antique

I just thought i'd stick my nose in here for a moment and mention a couple of issues observed and mentioned to me;


1) it would be nice if you included an Amiga version string in the next release, it's really inconvenient without one.

2) that DSI on startup is really annoying and you need to get a version out (even an interim one) that at least starts without a visit from the reaper, it's really unsettling.

3) Info being displayed in a plainer layout, specifically why there are two sets of up and down speeeds seperated by a comma. No-one seems to know why there are two lots of speed stats. Maybe a "newbie guide" could be deployed.

4) Why are the stats so unreliable, for example, if the first instance run says there are 3 seeders, 1 leecher and 5 peers, starting another instance on the exact same torrent may now report 8 seeders, 3 leechers and 10 peers while the first instance shown the same old values.


Anyway, there's a couple of things that I have found and some issues put to me from others.

Keep up the good work....

Go to top


Re: Completely detached process
Just popping in
Just popping in


@orgin


Seeing you can see the problem area ahead of you,
then make it so EVERY child can deallocate the seglist,
by creating the children with the same seglist tag,
but set the NP_FreeSegList,FALSE on child creation.

Then, use ProcessScan() at the exit point of the common
child code to find out how many of your child processes
are still running, and when the last one is exiting
(ie; only 1 child) then delegate that child to be the
process that frees the seglist by setting its
proc->pr_Flags |= PRF_FREESEGLIST; bit,
then simply return() to DOS.

There is example code in the ProcessScan() autodoc.
See the "SignalMyChildProcsToExit" example code and
just lose the Signal(), and use any of the child procs
pr_ParentID to scan for other descendants, it will return
the child process count.

Just beware of handlers being started up, therefore use
a second tier check, i'd suggest a magic cookie in
NP_UserData, or NP_EntryData or NP_ExitData or such,
when starting the actual child processes.

Enjoy...

Go to top


Re: Completely detached process
Just popping in
Just popping in


The subprocess is still running in the code space loaded for the parent.
The parent exits, unloads the code, subprocess crashes.
That's pretty well outlines your problem.

Two basic ways to fix this....

1) Use NP_Child tag and make the parent Wait()/WaitMsg()
until the child exits, see; NP_NotifyOnDeathMessage and NP_NotifyOnDeathSigTask.
Set up a message/signal and only allow the parent to leave only when the child notifies you of its death.
However, this means that the parent must go to sleep until the child exits, which means that if
the parent was a shell process, the CLI will be "dead" until the child ends.

2) If you wish to affect a complete detachment of the child and allow the parent to completely exit
while allowing the child to continue execution in the old code space, then the resources that are
shared by the child MUST also be detached.

This can be a little more complicated and not really for the beginner.
Nevertheless, here's an outline of what needs to be done.


The easiest way is to call CreateNewProc() with no tags for the NP_Input,NP_Output,NP_Error,
these will then open a default "NIL:" stream for the child (and 0 for the error stream).
(and with NP_Child,FALSE)

With that taken care of, (here's the tricky part), because as the seglist is being shared,
you must make sure it is not freed by the parent process on exit,

You can transfer ownership to the child process, so that it frees it on exit instead,
so it is not done by the parent.
To do this, you need to determine who loaded the original, this can be the shell or 'other'.
If the shell loaded it, you need to stop it from unloading the command on exit.

Here's some pseudocode.....

============

BPTR seg = ZERO;
struct CommandLineInterface *cli = IDOS->Cli();
if( cli )
{
seg = cli->cli_Module;
cli->cli_Module = ZERO; /* stop shell freeing the seg */
}
else /* not a cli, try 'other' load methods */
{
seg = IDOS->GetProcSegList(NULL,GPSLF_SEG);
if( seg )
{
struct Process *me = (struct Process *)FindTask(0);
me->pr_Flags &= (~PRF_FREESEGLIST);
} /* clear the flag for parent to free seglist */
}


if( seg ) /* did we find a loadsegged seglist ? */
{
IDOS->CreateNewProcTags(
NP_Entry, child_entry_func, /* entry() here */
NP_SegList, seg, /* free this seg on exit */
NP_FreeSegList,TRUE, /* make it so */
...
TAG_END);

}
else
{
PutStr("ERROR: Cannot find loaded seglist..\n");
}


NOTE WELL:
You cannot call newlib functions in the child process unless you re-open the library within
the child process itself, and set the childProc->pr_CLibData to the newlib base as there will
be no default library context available to the child.

Better to just use the IDOS-> functions while inside the child process.


Also note that as the child is now responsible for freeing the seglist on exit, you MUST make sure the parent now exits BEFORE the child does, otherwise you will find yourself in the same situation.

Go to top


Re: Stack usage tracking and stack size setting
Just popping in
Just popping in


@TSK

It does, to a point......

It will show you the amount of stack EVER written that
contains a non-zero default value.

It would not include the full size of a local stack buffer of say 5000 bytes, that only had 1000 bytes written to it,
the numbers would come up as 4000 bytes short in this case.

In other words, it calculates it from the first written non-zero value from the end of the frame, and shows that as the point of "usage" of the stack allocation.

However, for a guide it is close enough to be quite usefull.

Go to top


Re: Subprocess launching and communication.
Just popping in
Just popping in


@krashan
Quote:
AmigaOS 4 autodocs do not say I can look at DeathMessage from the subprocess.

You can, I thought that was implied by the name of the field.
The pointer is stored in pr_DeathMessage of the child process.

Go to top


Re: Subprocess launching and communication.
Just popping in
Just popping in


@colinw

Allow me to rephrase my last reply....
I was in a hurry to go out for dinner at the time.

As the previous reply from Salass00 indicated, you get a free ExecBase pointer when you enter the child entry() function of the code pointed to by NP_Entry.

See the include file; dos/startup.h
The child process starts up like all other processes in DOS do, just remember to declare the child process entry() just like that shown in startup.h.
Just don't call the child entry function _start(), that symbol name is reserved for the initial entry point of the main executable.

If you wish to pass additional parameters to the child, you can use any of the "Spare" process fields of the child process, as long as they can be initialised in the call to CreateNewProc() via tags.
For example; NP_EntryData, NP_ExitData, NP_FinalData, NP_UserData.....
These are all available for your general usage, you can even pass pointers in these fields, such as a custom parameter structure or such like.

NB: The NP_EntryData and NP_ExitData tag values can be obtained by calling IDOS->GetEntryData() or IDOS->GetExitData() from within the child process.
The other fields do not have accessor functions and would
require that you call; struct Process *child = IExec->FindTask(0); from the child process to to get the child process pointer and to then access those other fields.


When the child is running in the shared code space of the parent, all globals are accessible, but remember that you have to take care with data that is shared by the two processes and employ some sort of arbitration when modifying any global values as the child is running independantly of the parent.

Now, as far as NP_Child tag goes, it causes DOS to put the parent process to sleep for a while if the child is still running when the parent attempts to exit.
Once the child leaves, the parent is then allowed to exit fully and unload the program code.
This tag should be specified when a child is depending on any resources of the parent process.

Just remember that NP_Child is only for non-persistent child processes, as the parent will not be able to terminate until the child does so first.

Go to top


Re: Subprocess launching and communication.
Just popping in
Just popping in


@krashan

THe NP_Entry function has the ability to be passed a single parameter from the parent with the tag NP_EntryData.

That may be anything you wish, even a pointer to a
compound structure....

Go to top



TopTop
« 1 ... 3 4 5 (6) 7 »




Powered by XOOPS 2.0 © 2001-2023 The XOOPS Project