PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Benutzung von AIO unter Solaris 5.9


SimonX
2007-12-04, 13:12:10
Hi,

Ich habe ein Problem mit aio_fsync(). Unter Solaris hat die Funktion ein Memory-Leak obwohl ich glaube sie richtig zu benutzen.

Gibt es irgendwo Beispiel-Code, der aio_fsync() benutzt? Ich habe bis jetzt nur Testtreiber und Kernel-Code gefunden.

Ich habe versuchsweise man direkt hinter aio_fsync() die Warteschleife gemacht, damit da nichts anbrennt, aber das Memory-Leak ist immer noch da.

Das Testprogramm ruft nur SyncDataFile() auf.

Ein Stacktrace sieht so aus:

Program received signal SIGINT, Interrupt.
0xffffffff7e54f620 in _morecore () from /usr/lib/64/libc.so.1
(gdb) where
#0 0xffffffff7e54f620 in _morecore () from /usr/lib/64/libc.so.1
#1 0xffffffff7e54ed9c in _malloc_unlocked () from /usr/lib/64/libc.so.1
#2 0xffffffff7e54eb64 in malloc () from /usr/lib/64/libc.so.1
#3 0xffffffff7e105c0c in _aio_lio_alloc () from /usr/lib/64/libaio.so.1
#4 0xffffffff7e105e00 in __aio_fsync () from /usr/lib/64/libaio.so.1
#5 0x000000010000694c in SyncDataFile (fd=3) at fsync_test.c:53
#6 0x0000000100006f88 in main (ac=9, av=0xffffffff7fffef78) at fsync_test.c:128

Das Problem tritt auf wenn ich es im 64bit übersetzt habe aber auch in 32bit. Ich kann eigentlich nicht glauben, das in Solaris solche dicken Bugs sein sollen.

Ich habe schon verschiedenste Sachen probieren,



Hier der Code:


static int SyncDataFile(int fd)
{
static struct aiocb aio_req;
static int in_use=0;
int r;
int my_err;
int my_err_info=0;

if (in_use) {
my_err=aio_error(&aio_req);
if (my_err==EINPROGRESS) {
/**
* still busy. force normal sync.
*/
return -1;
}

if (my_err==-1) {
my_err_info=errno;
}

in_use=0;
r=aio_return(&aio_req);
if (r!=0 && (r!=-1 && my_err!=-1 && my_err_info!=EINVAL)) {
/**
* Last sync failed. force normal sync.
*/
return -1;
}
}
memset(&aio_req, 0, sizeof(aio_req));
aio_req.aio_fildes = fd;
aio_req.aio_sigevent.sigev_notify = SIGEV_NONE;
r=aio_fsync(O_DSYNC, &aio_req);
if (r==0) {
in_use=1;
while (in_use==1) {
my_err=aio_error(&aio_req);
if (my_err==EINPROGRESS) {
/**
* still busy. force normal sync.
*/
continue;
}

if (my_err==-1) {
my_err_info=errno;
}

in_use=0;
r=aio_return(&aio_req);
if (r!=0 && (r!=-1 && my_err!=-1 && my_err_info!=EINVAL)) {
/**
* Last sync failed. force normal sync.
*/
return -1;
}
}
} else {
aio_return(&aio_req);
}

return r;
}

SimonX
2007-12-04, 13:38:14
Es scheint so zu sein, das Solaris kein aio_fsync() für normale Files unterstützt. Denn aio_return gibt


69 in_use=0;
(gdb)
70 r=aio_return(&aio_req);
(gdb)
71 if (r!=0 && (r!=-1 && my_err!=-1 && my_err_info!=EINVAL)) {
(gdb) p aio_req
$5 = {aio_fildes = 3, aio_buf = 0x0, aio_nbytes = 0, aio_offset = 16, aio_reqprio = 0, aio_sigevent = {sigev_notify = 0, sigev_signo = 0,
sigev_value = {sival_int = 0, sival_ptr = 0x0}, sigev_notify_function = 0, sigev_notify_attributes = 0x0, __sigev_pad2 = 0},
aio_lio_opcode = 20, aio_resultp = {aio_return = -1, aio_errno = 22}, aio_state = 0, aio__pad = {0}}
(gdb)

zurück. aio_return=-1 und aio_errno=22 (EINVAL -> fsync() wird nicht unterstütz). Da fsync() aber sonst geht muss es das aio_fsync() des Filesystems selbst sein.

Also wieder zurück zu fdatasync() :-(