in opendir() prevented freezing up, so i suggest this change to libcglue.c in newlib.
Also readdir() is potential for memory leak, because it allocates new dirent structure for each
entry. Caller must release it explicitly and that is not what programs that use this function
do (traditionally this function returns pointer to static structure).
robif wrote:It seems that memory that is allocated for DIR structure in opendir() should be
initialized to zero, as current implementation causes PSP to freeze.
Do you have an example? It's working fine here. The DIR structure only contains a single element anyway, which clearly gets set in the very next line, so I don't see what initializing it to zero could possibly do.
robif wrote:
Also readdir() is potential for memory leak, because it allocates new dirent structure for each
entry. Caller must release it explicitly and that is not what programs that use this function
do (traditionally this function returns pointer to static structure).
readdir()'s buffer may be overwritten only for the same directory stream, so a single static structure is no good. We probably need to allocate a buffer in struct DIR and use that.
static PyObject* PyPSP_listdir(PyObject *self,
PyObject *args)
{
char *path;
DIR* dirp;
struct dirent* ent;
PyObject* ret;
if (!PyArg_ParseTuple(args, "s:listdir", &path))
return NULL;
dirp = opendir(path);
if (!dirp) {
PyErr_Format(PyExc_OSError, "Can't open directory %s", path);
return NULL;
}
ret = PyList_New(0);
while(1)
{
ent = readdir(dirp);
if (!ent)
{
break;
}
PyList_Append(ret, PyString_FromString(ent -> d_name));
free(ent);
}
if (closedir(dirp) < 0) {
Py_DECREF(ret);
ret = NULL;
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
return ret;
}
when i replaced malloc with calloc within opendir and readdir, it worked. This was on EU psp.
Of course it might be some other problem as it is called from within interpreter that does
other things...
Idea of storing ptr to dirent or dirent itself in DIR looks good, much better than static
struct.
I still say that there's no possible difference between calloc() and malloc() because the only variable in the DIR structure gets overwritten immediately anyway. If you can provide a small compilable example I'll check it out, but I suspect your problem is hidden elsewhere and is just being triggered by the slightly different call stack.
From mrbrown:
Actually, you have to memset() the dirent before calling sceIoDread(). Then it works on stack or global.
So maybe readdir() needs to memset dirent also before calling sceIoDread?
Must be that sceIoDread() tries to free buffers defined in the dirent? I also remember someone saying that sceIoDread() allocates memory and that the user is supposed to free it.. (unusual behaviour, if true, but it may explain the crashes when dirent is not initialized, if Dread tries to free...).
OK, rev 1172 has these changes (move dirent inside DIR, zero dirent before calling sceIoDread). Don't free the dirent returned by readdir() anymore. Let me know if it gives you any trouble.
jimparis wrote:OK, rev 1172 has these changes (move dirent inside DIR, zero dirent before calling sceIoDread). Don't free the dirent returned by readdir() anymore. Let me know if it gives you any trouble.