readdir() threadsafe?

This forum is for general developer support questions.
xenic
Posts: 1185
Joined: Sun Jun 19, 2011 1:06 am

Re: readdir() threadsafe?

Post 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.
Last edited by xenic on Mon Jun 25, 2012 5:51 pm, edited 2 times in total.
AmigaOne X1000 with 2GB memory - OS4.1 FE
User avatar
Slayer
Beta Tester
Beta Tester
Posts: 851
Joined: Tue Dec 21, 2010 4:19 am
Location: New Zealand

Re: readdir() threadsafe?

Post 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
~Yes I am a Kiwi, No, I did not appear as an extra in 'Lord of the Rings'~
1x AmigaOne X5000 2.0GHz 2gM RadeonR9280X AOS4.x
3x AmigaOne X1000 1.8GHz 2gM RadeonHD7970 AOS4.x
xenic
Posts: 1185
Joined: Sun Jun 19, 2011 1:06 am

Re: readdir() threadsafe?

Post 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.
AmigaOne X1000 with 2GB memory - OS4.1 FE
Post Reply