readdir() threadsafe?

This forum is for general developer support questions.

Re: readdir() threadsafe?

Postby xenic » Mon Jun 25, 2012 6:16 am

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 4:51 pm, edited 2 times in total.
AmigaOne X1000 with 2GB memory - OS4.1u6
xenic
 
Posts: 346
Joined: Sun Jun 19, 2011 12:06 am

Re: readdir() threadsafe?

Postby Slayer » Mon Jun 25, 2012 7:54 am

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'~
2x X1000 1.8GHz 2gM RadeonHD7970 AOS4.x
3x Sam Flex (667MHz, 733MHz & 800MHz models) 1gM Radeon9250 AOS4.x
Sam 667MHz .5gM RadeonM9 AOS4.x
A4000D 604e 233Mhz .125gM Voodoo3 AOS4.x
User avatar
Slayer
Beta Tester
Beta Tester
 
Posts: 702
Joined: Tue Dec 21, 2010 4:19 am
Location: New Zealand

Re: readdir() threadsafe?

Postby xenic » Mon Jun 25, 2012 4:59 pm

@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.1u6
xenic
 
Posts: 346
Joined: Sun Jun 19, 2011 12:06 am

Previous

Return to General Developer Support

Who is online

Users browsing this forum: Google [Bot] and 1 guest