Re: [AD] get_audio_stream_buffer

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Chris wrote:

Serge Semashko wrote:

Thanks for the hints, I have found a solution in gentoo forums and fixed this issue.

Would you care to share them with me, please? :)

I have just copied my current glibc ebuild to portage overlay, added
RESTRICT="nostrip" option to it and reemerged glibc. Seems that almost
all the other glibc ebuilds have this problem recently fixed, but not a
stable ebuild. Text from /usr/portage/sys-libc/glibc/ChangeLog:

02 Aug 2004; Mike Frysinger <vapier@xxxxxxxxxx> glibc-2.2.5-r9.ebuild,
glibc-2.3.2-r10.ebuild, glibc-2.3.4.20040619.ebuild:
Dont strip libthread_db and libpthread since it breaks gdb debugging
badly #46186.

So hopefully everything will be fixed soon :)

Examining this bug in gdb reveals the following information:

(gdb) bt
#0 _mix_some_samples (buf=1086511624, seg=42190, issigned=1) at src/mixer.c:1107
#1  0x08198475 in oss_update (threaded=1) at src/unix/uoss.c:176


Okay, it does look like some form of corruption. This is the only place in oss_update that calls _mix_some_samples:
     _mix_some_samples((unsigned long) oss_bufdata, 0, oss_signed);
As you can see, the segment passed is always 0, yet your backtrace shows 42190. And also, that memory address for the buffer looks dubious as well, being so high. I'd recommend running memtest86 or some other memory testing program.

Well, I tested the memory with memtest86 and it did not find any
problems. In addition, the same bug can be reproduced on a different
computer (with a very similar hardware and os). Have no idea what could
have happened with that 'seg' argument though.

(gdb) inspect bufinfo
$1 = {fragments = 2097151, fragstotal = 8, fragsize = 2048, bytes = -1536}


The fragments and bytes here look really bad as well. I'd likely guess your memory is going bad.

Well, looks like I have found how to easily reproduce the same problem
(test program is attached). The only way we can affect OSS driver from
oss_update function is to flood it with information and try to overflow
internal OSS driver buffers. This test program tries to write 4096 bytes
to OSS descriptor in a loop, checking bufinfo structure after every
write. I get the following results after running this program on my
computer (OSS emulated by ALSA 1.0.5, 'snd-via82xx' driver):

[test program output]
fragments = 16, fragstotal = 16, fragsize = 4096, bytes = 65536
fragments = 15, fragstotal = 16, fragsize = 4096, bytes = 61532
fragments = 14, fragstotal = 16, fragsize = 4096, bytes = 57532
fragments = 13, fragstotal = 16, fragsize = 4096, bytes = 53532
fragments = 12, fragstotal = 16, fragsize = 4096, bytes = 49532
fragments = 11, fragstotal = 16, fragsize = 4096, bytes = 45532
fragments = 10, fragstotal = 16, fragsize = 4096, bytes = 41532
fragments = 9, fragstotal = 16, fragsize = 4096, bytes = 37532
fragments = 8, fragstotal = 16, fragsize = 4096, bytes = 33532
fragments = 7, fragstotal = 16, fragsize = 4096, bytes = 29531
fragments = 6, fragstotal = 16, fragsize = 4096, bytes = 25531
fragments = 5, fragstotal = 16, fragsize = 4096, bytes = 21531
fragments = 4, fragstotal = 16, fragsize = 4096, bytes = 17531
fragments = 3, fragstotal = 16, fragsize = 4096, bytes = 13531
fragments = 2, fragstotal = 16, fragsize = 4096, bytes = 9530
fragments = 1, fragstotal = 16, fragsize = 4096, bytes = 5530
fragments = 0, fragstotal = 16, fragsize = 4096, bytes = 1530
fragments = 1048575, fragstotal = 16, fragsize = 4096, bytes = -2470
OSS bug detected
[/test program output]

Once this overflow occurs, the loop inside of oss_update function
becomes almost infinite as fragments field is used as a loop counter.
A different question is how allegro actually manages to write more data
to OSS than it had expected?

Maybe I will also try to recompile my kernel with OSS instead of ALSA
and run this test on it, but I'm too tired of all these tests already :)

Well, probably I will try to contact ALSA people now. Don't know if a
workaraund for this problem would be useful in allergo (maybe it could
just exit from oss_update loop when bytes field is negative or fragments
is greater than fragstotal). Maybe sound will be broken in this case,
but the game will not freeze at least.


#include <sys/soundcard.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int oss_fd = open("/dev/dsp", O_WRONLY | O_NONBLOCK);

bool check_oss_bug()
{
   audio_buf_info bufinfo;
   if (ioctl(oss_fd, SNDCTL_DSP_GETOSPACE, &bufinfo) != -1) {
      printf("fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d\n", 
	     bufinfo.fragments, bufinfo.fragstotal, bufinfo.fragsize, bufinfo.bytes);
      if (bufinfo.fragments > bufinfo.fragstotal) {
         printf("OSS bug detected\n");
		 return true;
   	  }
   }
   return false;
}

void oss_write(int size)
{
   char *buf = new char[size];
   memset(buf, 0, size);
   int result = write(oss_fd, buf, size);
   if (result != size)
      printf("tried to write %d bytes, actually written %d\n", size, result);
   delete [] buf;
}

int main()
{
   while (!check_oss_bug()) {
      oss_write(4096);
	  usleep(10000);
   }
   return 0;
}



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/