Page 2 of 2

Re: readdir() threadsafe?

Posted: Mon Jun 25, 2012 7:16 am
by xenic
chris wrote:That sounds like a bug in newlib.library.
I added a readdir() loop to my test program and the lack of a lock isn't a exactly a bug; it's just dumb on a multitasking system like AmigaOS. It seems that opendir() reads the directory into a buffer and readdir() reads the files from the buffer. That means that the directory or files can be changed or deleted by another application after opendir() is called and readdir() will still show files that have changed or been deleted.

On the other hand, if I compile my test program with clib2 then opendir() and readdir() function like AmigaDOS and the directory is locked and the files are locked/read read as the application requests the next file in an examine loop.

You should be able to compile my test program and see what I mean. Just create a test directory in ram: (with files) and run the test program in a shell (opendir ram:testdir), delete the directory from another shell and then enter Ctrl-E in the shell you ran the program from. You should see a list of files that have been deleted.

Code: Select all

/* Compile: gcc -O2 opendir.c -o OpenDir -Wall -lauto */

#include <signal.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <dirent.h>
#include <strings.h>
#include <string.h>

#define TEMPLATE "DIR/A,DELAY/K/N"

struct RDArgs *argsdata;
DIR *dirt = NULL;

enum
{
O_DIR, O_DELAY, O_MAX
};

static void cleanup();

int main(int argc, char **argv)
{
int32 args[O_MAX] = {0};
int32 time = 0;
int32 delay = 0;
uint32 signals = 0;
struct dirent *entry = NULL;

signal(SIGINT, SIG_IGN);
if (argc == 0)
{
IDOS->PutErrStr("Error: Shell program\n");
return(RETURN_ERROR);
}

argsdata = IDOS->ReadArgs(TEMPLATE, args, NULL);
if (!argsdata)
{
IDOS->PrintFault(IDOS->IoErr(), "Error");
cleanup();
return(RETURN_ERROR);
}

if (args[O_DELAY])
delay = *(int32 *)args[O_DELAY];
if ((delay > 0) && (delay < 300))
time = delay * 50;

if (args[O_DIR])
{
dirt = opendir((char *)args[O_DIR]);
if (!dirt)
{
IDOS->Printf("Directory not found\n");
cleanup();
return(RETURN_ERROR);
}
}

if (time > 0)
{
IDOS->Printf("Opened %s - Waiting %ld Seconds\n", args[O_DIR], delay);
IDOS->Delay(time);
}
else
{
IDOS->Printf("Opened %s - Waiting for Ctrl-E\n", args[O_DIR]);
signals = IExec->Wait(SIGBREAKF_CTRL_E);
}


while ((entry = readdir(dirt)))
{
if ((strcmp(entry->d_name, ".") == 0)||(strcmp(entry->d_name, "..") == 0))
continue;
IDOS->Printf("Filename is %s\n", entry->d_name);
}

cleanup();
return(RETURN_OK);
}

void cleanup(void)
{
if (dirt) closedir(dirt);
if (argsdata) IDOS->FreeArgs(argsdata);
}

Personally, I would feel safer compiling with clib2 or using the AmigaDOS directory functions rather than the newlib opendir() and readdir() functions. Buffering a large directory on a multitasking system makes no sense.

Re: readdir() threadsafe?

Posted: Mon Jun 25, 2012 8:54 am
by Slayer
There is a problem with your code

I get this repeating

-----8<-----
opendir.c:76: error: stray '\240' in program
opendir.c:76: error: stray '\240' in program
opendir.c:77: error: stray '\240' in program
opendir.c:77: error: stray '\240' in program
opendir.c:79: error: stray '\240' in program
opendir.c:79: error: stray '\240' in program
opendir.c:80: error: stray '\240' in program
opendir.c:80: error: stray '\240' in program
opendir.c: In function 'cleanup':
opendir.c:85: error: stray '\240' in program
opendir.c:85: error: stray '\240' in program
opendir.c:86: error: stray '\240' in program
opendir.c:86: error: stray '\240' in program

Re: readdir() threadsafe?

Posted: Mon Jun 25, 2012 5:59 pm
by xenic
@slayer
Yes. You're right. When you copy the program and paste it in an editor, the leading spaces contain non-printable characters. I would have thought that the purpose of the "Select All" link above a code section is to be able to copy the code and paste it in a text editor for saving and compiling. I removed the leading spaces and you should now be able to copy the code, paste it in an editor, save it and compile it. Removing the leading spaces makes the code difficult to read and makes the "code" block somewhat useless. Maybe there is some trick to get proper copyable code with leading spaces into a "code" block but I can't find a way to do it.