// read or write?
if (ML_(safe_to_deref)((struct vki_aiocb *)ARG1, sizeof(struct vki_aiocb))) {
SET_STATUS_from_SysRes(VG_(do_syscall1)(SYSNO, ARG1));
- if (SUCCESS) {
+ /*if (SUCCESS)*/ {
struct vki_aiocb* iocb = (struct vki_aiocb*)ARG1;
if (!aio_init_done) {
aio_init();
if (!aiov_init_done) {
aiov_init();
}
+
+ // for the happy path aio_return is supposed to be called
+ // after the io has completed (as determined by aio_error,
+ // aio_suspend or a signal).
+
+ // but what if the aio_read failed or hasn't completed?
+ // we want to remove the read from the iocb(v)_table
+ // in the case of aio_read failing
+ // if the read hasn't completed that's a user error
+ // I don't know if it's possible to recover in that case
+ // the iocb will have been removed from the table
+ // so if the user does recover and call aio_return
+ // 'correctly' we won't do the POST_MEM_WRITE
+ // I don't think that we can tell apart a failing
+ // read from a premature aio_return
+
// check if it was a plain read
- if (VG_(OSetWord_Remove)(iocb_table, (UWord)iocb)) {
+ if (VG_(OSetWord_Remove)(iocb_table, (UWord)iocb) && SUCCESS) {
POST_MEM_WRITE((Addr)iocb->aio_buf, iocb->aio_nbytes);
}
- if (VG_(OSetWord_Remove)(iocbv_table, (UWord)iocb)) {
+ if (VG_(OSetWord_Remove)(iocbv_table, (UWord)iocb) && SUCCESS) {
SizeT vec_count = (SizeT)iocb->aio_nbytes;
// assume that id the read succeded p_iovec is accessible
volatile struct vki_iovec* p_iovec = (volatile struct vki_iovec*)iocb->aio_buf;
assert( aio_read(&a) < 0 ); // (don't crash on the repeated &a)
- while (0 != aio_error(&a)) { };
+ while (0 != aio_error(&a)) { }
if (buf[0] == buf[9]) x++; // undefined -- aio_return() not called yet
assert( aio_write(&a) < 0 ); // (don't crash on the repeated &a)
- while (0 != aio_error(&a)) { };
+ while (0 != aio_error(&a)) { }
assert( aio_return(&a) > 0 );
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
+#include <time.h>
+#include <errno.h>
int x;
int main(void)
assert(a.aio_fildes >= 0);
// unaddressable aio_buf
- assert(aio_read(&a) == 0);
- assert(aio_return(&a) == -1);
+ //assert(aio_read(&a) == 0);
+ //assert(aio_return(&a) == -1);
//------------------------------------------------------------------------
a.aio_buf = buf;
assert( aio_read(&a) == 0 );
-
- // undefined -- aio_return() not called yet
- if (buf[0] == buf[9]) x++;
// also failed on macOS
// (don't crash on the repeated &a)
- assert( aio_read(&a) == 0 );
+ // assert( aio_read(&a) < 0 );
+
+ // undefined -- aio_return() not called yet
+ if (buf[0] == buf[9]) x++;
int try_count = 0;
- while (0 != aio_error(&a) && try_count < 10000) {
+ int res = aio_error(&a);
+ while (0 != res && try_count < 1000) {
++try_count;
+ struct timespec rq = { 0, 1000 };
+ nanosleep(&rq, NULL);
+ res = aio_error(&a);
}
-
- assert(try_count < 10000);
+
+ assert(try_count < 1000);
assert( aio_return(&a) > 0 ); // XXX: (undefined value error here)
if (buf[0] == buf[9]) x++;
- assert( aio_return(&a) > 0 ); // (repeated aio_return(); fails because
+#if 0
+ assert( aio_return(&a) < 0 ); // (repeated aio_return(); fails because
// Valgrind can't find &a in the table)
+#endif
//------------------------------------------------------------------------
a.aio_buf = 0;
assert(a.aio_fildes >= 0);
// unaddressable aio_buf
- assert( aio_write(&a) == 0);
- assert(aio_return(&a) == -1);
+ //assert( aio_write(&a) == 0);
+ //assert(aio_return(&a) == -1);
//------------------------------------------------------------------------
a.aio_buf = buf;
assert( aio_write(&a) == 0 );
// (don't crash on the repeated &a)
- assert( aio_write(&a) == 0 );
+ //assert( aio_write(&a) < 0 );
+
+ try_count = 0;
+ res = aio_error(&a);
+ while (0 != res && try_count < 1000) {
+ ++try_count;
+ struct timespec rq = { 0, 1000 };
+ nanosleep(&rq, NULL);
+ res = aio_error(&a);
+ }
- while (0 != aio_error(&a)) { }
+ assert(try_count < 1000);
assert( aio_return(&a) > 0 );
- assert( aio_return(&a) > 0 ); // (repeated aio_return(); fails because
+#if 0
+ assert( aio_return(&a) < 0 ); // (repeated aio_return(); fails because
// Valgrind can't find &a in the table)
+#endif
unlink("mytmpfile");
Warning: invalid file descriptor -1 in syscall aio_read()
-Syscall param aio_read(aiocbp->aio_buf) points to unaddressable byte(s)
- at 0x........: aio_read (in /...libc...)
- by 0x........: main (aio.c:47)
- Address 0x........ is not stack'd, malloc'd or (recently) free'd
-
-Conditional jump or move depends on uninitialised value(s)
- at 0x........: main (aio.c:56)
-
-Warning: Duplicate control block 0x........ in aio_read
-Warning: Ensure 'aio_return' is called when 'aio_read' has completed
Conditional jump or move depends on uninitialised value(s)
- at 0x........: aio_read (in /...libc...)
- by 0x........: main (aio.c:60)
-
-Syscall param aio_write(iocb->aio_buf) points to unaddressable byte(s)
- at 0x........: aio_write (in /...libc...)
- by 0x........: main (aio.c:82)
- Address 0x........ is not stack'd, malloc'd or (recently) free'd
+ at 0x........: main (aio.c:62)
HEAP SUMMARY:
Use --track-origins=yes to see where uninitialised values come from
For lists of detected and suppressed errors, rerun with: -s
-ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)