All of lore.kernel.org
 help / color / mirror / Atom feed
* ALSA driver 1.0.2c: divide by zero oops
@ 2004-03-14 23:17 Jonathan Woithe
  2004-03-15 10:44 ` Takashi Iwai
  0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Woithe @ 2004-03-14 23:17 UTC (permalink / raw)
  To: alsa-devel; +Cc: Jonathan Woithe

Hi all

I have been trying cinelerra 1.1.9 in OSS mode against the OSS emulation
driver (snd-pcm-oss) from ALSA driver 1.0.2c. Whenever anything is done to
start audio playback (such as playing a video clip) the ALSA driver panics
with a divide by zero error.  The decoded oops is found below.

Under native OSS from 2.4.23 cinelerra works fine.  Furthermore, all other
OSS applications I've tried against ALSA driver 1.0.2c seem to be fine. 
Thus the problem seems to be associated with the way cinelerra does things -
something it does is upsetting ALSA but is fine under native OSS.  Of
course, even a misbehaving application not running as root should not be
able to panic the kernel.

Tracing though this it appears that the substream's rate is zero heading
into snd_pcm_timer_resolution_change and the divide by zero occurs as a
result of the final statement in this function.  Why the rate is zero to
begin with though is a mystery to me.

I've checked cinelerra/audiooss.C and the order of the OSS ioctls during 
setup at least appears to be correct.

I'll check 1.0.3 in the next day or so but in a quick check of the CVS logs
I saw nothing to indicate that anything in this area might have changed.

Anyone have any ideas?

Mar 14 14:26:04 marble kernel: CPU:    0
Mar 14 14:26:04 marble kernel: EIP:    0010:[<d8c31a28>]    Not tainted
Using defaults from ksymoops -t elf32-i386 -a i386
Mar 14 14:26:04 marble kernel: EFLAGS: 00010246
Mar 14 14:26:04 marble kernel: eax: ee6b0000   ebx: 00008000   ecx: 00008000   edx: 00000000
Mar 14 14:26:04 marble kernel: esi: 00000000   edi: ee6b0000   ebp: d3805800   esp: ce88b918
Mar 14 14:26:04 marble kernel: ds: 0018   es: 0018   ss: 0018
Mar 14 14:26:04 marble kernel: Process cinelerra (pid: 354, stackpage=ce88b000)
Mar 14 14:26:04 marble kernel: Stack: 00000fa9 00008000 d3805800 00000001 ce88b95c c15a8d60 d8c28469 c15a8d60 
Mar 14 14:26:04 marble kernel:        00010000 ce88a000 ce88b95c cdba7400 ce88bca4 d8c28584 c15a8d60 ce88b95c 
Mar 14 14:26:04 marble kernel:        0000025c 00000000 00000008 00000000 00000000 00000000 00000000 00000000 
Mar 14 14:26:04 marble kernel: Call Trace:    [<d8c28469>] [<d8c28584>] [<d8c2b756>] [<d8c2fe96>] [<d8c2be18>]
Mar 14 14:26:04 marble kernel:   [<d8c6dad1>] [<d8c6df0e>] [<d8c6ee93>] [<c014f4c6>] [<c01a98b0>] [<c014f782>]
Mar 14 14:26:04 marble kernel:   [<c01a98b0>] [<c01a9951>] [<c0133134>] [<d8c0b6cf>] [<d8c2e65c>] [<d8c2a9dd>]
Mar 14 14:26:04 marble kernel:   [<d8c6fc92>] [<d8c6ff57>] [<c014726e>] [<d8bf3d40>] [<d8c760e0>] [<d8bf365f>]
Mar 14 14:26:04 marble kernel:   [<c013a58c>] [<c023f38e>] [<c0124fc3>] [<c013a6ee>] [<d8c6efdc>] [<d8c705cb>]
Mar 14 14:26:04 marble kernel:   [<c0148689>] [<c01090ef>]
Mar 14 14:26:04 marble kernel: Code: f7 f6 89 85 0c 02 00 00 83 c4 08 5b 5e 5f 5d c3 90 8d b4 26 


>>EIP; d8c31a28 <[snd-pcm]snd_pcm_timer_resolution_change+88/a0>   <=====

>>ebp; d3805800 <_end+13491b1c/1881c37c>
>>esp; ce88b918 <_end+e517c34/1881c37c>

Trace; d8c28469 <[snd-pcm]snd_pcm_hw_params+209/2b0>
Trace; d8c28584 <[snd-pcm]snd_pcm_hw_params_user+74/a0>
Trace; d8c2b756 <[snd-pcm]snd_pcm_playback_ioctl1+56/340>
Trace; d8c2fe96 <[snd-pcm]snd_pcm_hw_param_near+256/320>
Trace; d8c2be18 <[snd-pcm]snd_pcm_kernel_playback_ioctl+38/50>
Trace; d8c6dad1 <[snd-pcm-oss]snd_pcm_oss_change_params+3e1/7d0>
Trace; d8c6df0e <[snd-pcm-oss]snd_pcm_oss_get_active_substream+4e/60>
Trace; d8c6ee93 <[snd-pcm-oss]snd_pcm_oss_get_formats+23/140>
Trace; c014f4c6 <get_new_inode+146/160>
Trace; c01a98b0 <reiserfs_find_actor+0/40>
Trace; c014f782 <iget4+e2/f0>
Trace; c01a98b0 <reiserfs_find_actor+0/40>
Trace; c01a9951 <reiserfs_iget+61/80>
Trace; c0133134 <__alloc_pages+64/280>
Trace; d8c0b6cf <[snd]snd_kcalloc+1f/50>
Trace; d8c2e65c <[snd-pcm]snd_pcm_hw_constraint_minmax+3c/40>
Trace; d8c2a9dd <[snd-pcm]snd_pcm_hw_constraints_complete+1fd/230>
Trace; d8c6fc92 <[snd-pcm-oss]snd_pcm_oss_open_file+162/240>
Trace; d8c6ff57 <[snd-pcm-oss]snd_pcm_oss_open+1e7/2c0>
Trace; c014726e <page_follow_link+4e/50>
Trace; d8bf3d40 <[soundcore]sound_loader_lock+0/0>
Trace; d8c760e0 <[snd-pcm-oss]snd_pcm_oss_f_reg+0/48>
Trace; d8bf365f <[soundcore]soundcore_open+df/190>
Trace; c013a58c <get_chrfops+ec/100>
Trace; c023f38e <sock_write+ae/c0>
Trace; c0124fc3 <in_group_p+23/30>
Trace; c013a6ee <chrdev_open+5e/70>
Trace; d8c6efdc <[snd-pcm-oss]snd_pcm_oss_set_format+2c/60>
Trace; d8c705cb <[snd-pcm-oss]snd_pcm_oss_ioctl+4fb/790>
Trace; c0148689 <sys_ioctl+c9/250>
Trace; c01090ef <system_call+33/38>

Code;  d8c31a28 <[snd-pcm]snd_pcm_timer_resolution_change+88/a0>
00000000 <_EIP>:
Code;  d8c31a28 <[snd-pcm]snd_pcm_timer_resolution_change+88/a0>   <=====
   0:   f7 f6                     div    %esi   <=====
Code;  d8c31a2a <[snd-pcm]snd_pcm_timer_resolution_change+8a/a0>
   2:   89 85 0c 02 00 00         mov    %eax,0x20c(%ebp)
Code;  d8c31a30 <[snd-pcm]snd_pcm_timer_resolution_change+90/a0>
   8:   83 c4 08                  add    $0x8,%esp
Code;  d8c31a33 <[snd-pcm]snd_pcm_timer_resolution_change+93/a0>
   b:   5b                        pop    %ebx
Code;  d8c31a34 <[snd-pcm]snd_pcm_timer_resolution_change+94/a0>
   c:   5e                        pop    %esi
Code;  d8c31a35 <[snd-pcm]snd_pcm_timer_resolution_change+95/a0>
   d:   5f                        pop    %edi
Code;  d8c31a36 <[snd-pcm]snd_pcm_timer_resolution_change+96/a0>
   e:   5d                        pop    %ebp
Code;  d8c31a37 <[snd-pcm]snd_pcm_timer_resolution_change+97/a0>
   f:   c3                        ret    
Code;  d8c31a38 <[snd-pcm]snd_pcm_timer_resolution_change+98/a0>
  10:   90                        nop    
Code;  d8c31a39 <[snd-pcm]snd_pcm_timer_resolution_change+99/a0>
  11:   8d b4 26 00 00 00 00      lea    0x0(%esi,1),%esi

Regards
  jonathan
-- 
* Jonathan Woithe    jwoithe@physics.adelaide.edu.au                        *
*                    http://www.physics.adelaide.edu.au/~jwoithe            *
***-----------------------------------------------------------------------***
** "Time is an illusion; lunchtime doubly so"                              **
*  "...you wouldn't recognize a subtle plan if it painted itself purple and *
*   danced naked on a harpsichord singing 'subtle plans are here again'"    *


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ALSA driver 1.0.2c: divide by zero oops
  2004-03-14 23:17 ALSA driver 1.0.2c: divide by zero oops Jonathan Woithe
@ 2004-03-15 10:44 ` Takashi Iwai
  2004-03-15 22:15   ` Jonathan Woithe
  0 siblings, 1 reply; 8+ messages in thread
From: Takashi Iwai @ 2004-03-15 10:44 UTC (permalink / raw)
  To: Jonathan Woithe; +Cc: alsa-devel

At Mon, 15 Mar 2004 09:47:07 +1030 (CST),
Jonathan Woithe wrote:
> 
> Hi all
> 
> I have been trying cinelerra 1.1.9 in OSS mode against the OSS emulation
> driver (snd-pcm-oss) from ALSA driver 1.0.2c. Whenever anything is done to
> start audio playback (such as playing a video clip) the ALSA driver panics
> with a divide by zero error.  The decoded oops is found below.
> 
> Under native OSS from 2.4.23 cinelerra works fine.  Furthermore, all other
> OSS applications I've tried against ALSA driver 1.0.2c seem to be fine. 
> Thus the problem seems to be associated with the way cinelerra does things -
> something it does is upsetting ALSA but is fine under native OSS.  Of
> course, even a misbehaving application not running as root should not be
> able to panic the kernel.

sure.  what soundcard/soundchip are you using?
also, did you compile with the debug option?
the zero devision is already checked with snd_assert() macro in 
snd_pcm_timer_resolution() if it happens there.


Takashi


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ALSA driver 1.0.2c: divide by zero oops
  2004-03-15 10:44 ` Takashi Iwai
@ 2004-03-15 22:15   ` Jonathan Woithe
  2004-03-16 10:40     ` Takashi Iwai
  0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Woithe @ 2004-03-15 22:15 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Jonathan Woithe, alsa-devel

> > I have been trying cinelerra 1.1.9 in OSS mode against the OSS emulation
> > driver (snd-pcm-oss) from ALSA driver 1.0.2c. Whenever anything is done to
> > start audio playback (such as playing a video clip) the ALSA driver panics
> > with a divide by zero error.  The decoded oops is found below.
> > 
> > Under native OSS from 2.4.23 cinelerra works fine.  Furthermore, all other
> > OSS applications I've tried against ALSA driver 1.0.2c seem to be fine. 
> > Thus the problem seems to be associated with the way cinelerra does things -
> > something it does is upsetting ALSA but is fine under native OSS.  Of
> > course, even a misbehaving application not running as root should not be
> > able to panic the kernel.
> 
> sure.  what soundcard/soundchip are you using?

It's an Ensoniq AudioPCI card with the ES-1370 chipset.

> also, did you compile with the debug option?

No.  Should I?  I'm guessing you may be after further debugging output
here - if so, what would you like me to do (after compiling with the debug
option)?

Regards
  jonathan
-- 
* Jonathan Woithe    jwoithe@physics.adelaide.edu.au                        *
*                    http://www.physics.adelaide.edu.au/~jwoithe            *
***-----------------------------------------------------------------------***
** "Time is an illusion; lunchtime doubly so"                              **
*  "...you wouldn't recognize a subtle plan if it painted itself purple and *
*   danced naked on a harpsichord singing 'subtle plans are here again'"    *


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ALSA driver 1.0.2c: divide by zero oops
  2004-03-15 22:15   ` Jonathan Woithe
@ 2004-03-16 10:40     ` Takashi Iwai
  2004-03-17 22:30       ` Jonathan Woithe
  0 siblings, 1 reply; 8+ messages in thread
From: Takashi Iwai @ 2004-03-16 10:40 UTC (permalink / raw)
  To: Jonathan Woithe; +Cc: alsa-devel

At Tue, 16 Mar 2004 08:45:00 +1030 (CST),
Jonathan Woithe wrote:
> 
> > > I have been trying cinelerra 1.1.9 in OSS mode against the OSS emulation
> > > driver (snd-pcm-oss) from ALSA driver 1.0.2c. Whenever anything is done to
> > > start audio playback (such as playing a video clip) the ALSA driver panics
> > > with a divide by zero error.  The decoded oops is found below.
> > > 
> > > Under native OSS from 2.4.23 cinelerra works fine.  Furthermore, all other
> > > OSS applications I've tried against ALSA driver 1.0.2c seem to be fine. 
> > > Thus the problem seems to be associated with the way cinelerra does things -
> > > something it does is upsetting ALSA but is fine under native OSS.  Of
> > > course, even a misbehaving application not running as root should not be
> > > able to panic the kernel.
> > 
> > sure.  what soundcard/soundchip are you using?
> 
> It's an Ensoniq AudioPCI card with the ES-1370 chipset.
> 
> > also, did you compile with the debug option?
> 
> No.  Should I?  I'm guessing you may be after further debugging output
> here - if so, what would you like me to do (after compiling with the debug
> option)?

please turn on the debug option.  it will help to catch the bug there,
at least we can know whether it's really zero division.


Takashi


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ALSA driver 1.0.2c: divide by zero oops
  2004-03-16 10:40     ` Takashi Iwai
@ 2004-03-17 22:30       ` Jonathan Woithe
  2004-03-18  8:58         ` Jaroslav Kysela
  0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Woithe @ 2004-03-17 22:30 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Jonathan Woithe, alsa-devel

Takashi

> > > > I have been trying cinelerra 1.1.9 in OSS mode against the OSS emulation
> > > > driver (snd-pcm-oss) from ALSA driver 1.0.2c. Whenever anything is done to
> > > > start audio playback (such as playing a video clip) the ALSA driver panics
> > > > with a divide by zero error.  The decoded oops is found below.
> > > > 
> > > > Under native OSS from 2.4.23 cinelerra works fine.  Furthermore, all other
> > > > OSS applications I've tried against ALSA driver 1.0.2c seem to be fine. 
> > > > Thus the problem seems to be associated with the way cinelerra does things -
> > > > something it does is upsetting ALSA but is fine under native OSS.  Of
> > > > course, even a misbehaving application not running as root should not be
> > > > able to panic the kernel.
> > > 
> > > sure.  what soundcard/soundchip are you using?
> > 
> > It's an Ensoniq AudioPCI card with the ES-1370 chipset.
> :
> please turn on the debug option.  it will help to catch the bug there,
> at least we can know whether it's really zero division.

I did this last night.  The following is my analysis of the problem.

With full debug selected, the only message reported by the ALSA system is
  ALSA ../alsa-kernel/core/pcm_timer.c:70: BUG? (rate != 0) 
  (called from d8c33a79)
That is, the assertion "rate!=0" fails.  This confirms the reported oops
trigger (that is, divide by zero).

Address d8c33a79 appears to be in snd_pcm_hw_params().  The call to 
snd_pcm_timer_resolution_change() appears at pcm_native.c:396.

In debug mode the divide isn't done when rate==0: the action in response to
the failed assertion is to return before attempting the divide.  When using
the debug mode ALSA driver cinelerra appears to function without any
immediately apparent problems (except of course the above debug message is
sent to the logs).

The earliest ALSA call in the previously reported oops backtrace appears to
be snd_pcm_oss_set_format(), which is called via the SNDCTL_DSP_SETFMT
ioctl.

cinelerra calls SNDCTL_DSP_SETFMT in a number of places in audiooss.C:
* AudioOSS::open_input():
    if(ioctl(dsp_in[i], SNDCTL_DSP_SETFRAGMENT, &buffer_info))
      printf("SNDCTL_DSP_SETFRAGMENT failed.\n");
    if(ioctl(dsp_in[i], SNDCTL_DSP_SETFMT, &format) < 0)
      printf("SNDCTL_DSP_SETFMT failed\n");
    if(ioctl(dsp_in[i], SNDCTL_DSP_CHANNELS,&device->in_config->oss_in_channels[i]) < 0) 
      printf("SNDCTL_DSP_CHANNELS failed\n");
    if(ioctl(dsp_in[i], SNDCTL_DSP_SPEED,&device->in_samplerate) < 0) 
      printf("SNDCTL_DSP_SPEED failed\n");
* AudioOSS::open_output():
    dsp_out[i] = open(device->out_config->oss_out_device[i],
                 O_WRONLY /*| O_NDELAY*/);
    set_cloexec_flag(dsp_out[i], 1);
    if(ioctl(dsp_out[i], SNDCTL_DSP_SETFRAGMENT, &buffer_info))
      printf("SNDCTL_DSP_SETFRAGMENT 2 failed.\n");
    if(ioctl(dsp_out[i], SNDCTL_DSP_SETFMT, &format) < 0) 
      printf("SNDCTL_DSP_SETFMT 2 failed\n");
    if(ioctl(dsp_out[i], SNDCTL_DSP_CHANNELS, &device->out_config->oss_out_channels[i]) < 0) 
      printf("SNDCTL_DSP_CHANNELS 2 failed\n");
    if(ioctl(dsp_out[i], SNDCTL_DSP_SPEED,&device->out_samplerate) < 0) 
      printf("SNDCTL_DSP_SPEED 2 failed\n");
    ioctl(dsp_out[i], SNDCTL_DSP_GETOSPACE, &playinfo);
* AudioOSS::open_duplex():
    As for AudioOSS::open_output() with
      if(ioctl(dsp_duplex[i], SNDCTL_DSP_SETDUPLEX, 1) == -1)
        printf("SNDCTL_DSP_SETDUPLEX failed\n");
    added after SNDCTL_DSP_SETFRAGMENT call.

In the case of the oops AudioOSS::open_output() was the function being used.
The SNDCTL_DSP_SETFMT call triggering the oops is preceeded with a call to
SNDCTL_DSP_SETFRAGMENT.  Commenting out the SNDCTL_DSP_SETFRAGMENT call
makes the "rate!=0" assertion pass - in other words, it appears that rate
becomes zero as a consequence of calling SNDCTL_DSP_SETFRAGMENT.  Thus the
problem would appear to be the SNDCTL_DSP_SETFRAGMENT preceeding
SNDCTL_DSP_SETFMT call.  Since cinelerra's call sequence for setting up OSS
devices (as shown above) agrees with the published API it therefore appears
that there is a glitch in the ALSA emulation system.

The other OSS apps I've used do not call SNDCTL_DSP_SETFRAGMENT which
probably explains why I've had no problem with other OSS applications.

I hope this helps track down the problem.  I am happy to run more tests if
needed.

Regards
  jonathan
-- 
* Jonathan Woithe    jwoithe@physics.adelaide.edu.au                        *
*                    http://www.physics.adelaide.edu.au/~jwoithe            *
***-----------------------------------------------------------------------***
** "Time is an illusion; lunchtime doubly so"                              **
*  "...you wouldn't recognize a subtle plan if it painted itself purple and *
*   danced naked on a harpsichord singing 'subtle plans are here again'"    *


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ALSA driver 1.0.2c: divide by zero oops
  2004-03-17 22:30       ` Jonathan Woithe
@ 2004-03-18  8:58         ` Jaroslav Kysela
  2004-03-23  5:51           ` Jonathan Woithe
  0 siblings, 1 reply; 8+ messages in thread
From: Jaroslav Kysela @ 2004-03-18  8:58 UTC (permalink / raw)
  To: Jonathan Woithe; +Cc: Takashi Iwai, alsa-devel

On Thu, 18 Mar 2004, Jonathan Woithe wrote:

> I did this last night.  The following is my analysis of the problem.
> 
> With full debug selected, the only message reported by the ALSA system is
>   ALSA ../alsa-kernel/core/pcm_timer.c:70: BUG? (rate != 0) 
>   (called from d8c33a79)
> That is, the assertion "rate!=0" fails.  This confirms the reported oops
> trigger (that is, divide by zero).

Could you add exactly same initialization sequence to 
alsa-oss/test/testoss.c code? So we can debug easily the problem here.
Thanks.

						Jaroslav

-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ALSA driver 1.0.2c: divide by zero oops
  2004-03-18  8:58         ` Jaroslav Kysela
@ 2004-03-23  5:51           ` Jonathan Woithe
  2004-03-23  8:49             ` Jaroslav Kysela
  0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Woithe @ 2004-03-23  5:51 UTC (permalink / raw)
  To: Jaroslav Kysela; +Cc: Jonathan Woithe, Takashi Iwai, alsa-devel

Hi all

> > I did this last night.  The following is my analysis of the problem.
> > With full debug selected, the only message reported by the ALSA system is
> >   ALSA ../alsa-kernel/core/pcm_timer.c:70: BUG? (rate != 0) 
> >   (called from d8c33a79)
> > That is, the assertion "rate!=0" fails.  This confirms the reported oops
> > trigger (that is, divide by zero).
> 
> Could you add exactly same initialization sequence to 
> alsa-oss/test/testoss.c code? So we can debug easily the problem here.

Sorry, I couldn't see where this would fit in in this file - testoss.c seems
more like it's testing the oss redirector though.  The bug I'm seeing is in
software which uses the oss emulation layer directly (that is, it accesses
/dev/dsp with no knowledge of ALSA).

To this end I've hacked up the following small C program which triggers the
fault (see the end of this email).  It essentially contains the exact same
initialisation sequence used in cinelerra 1.1.9.  In developing this program
I've made some more potentially interesting observations.

The divide by zero in snd_pcm_timer_resolution_change() is always triggered
by the SNDCTL_DSP_SETFMT ioctl following the SNDCTL_DSP_SETFRAGMENT. 
However, not all arguments to SNDCTL_DSP_SETFRAGMENT cause a problem.
The argument to SNDCTL_DSP_SETFRAGMENT is set to 
  (4 << 16) | XX
where XX is some number indicating the size of the buffer.  If XX<=14 then
ALSA works fine.  If, however, XX is 15 or greater we get the divide by zero
in snd_pcm_timer_resolution_change() during the following SNDCTL_DSP_SETFMT
call.

In cinelerra the default settings result in XX being set to 16 which is why
this application triggers the bug.  Other OSS applications either never call
the SNDCTL_DSP_SETFRAGMENT ioctl OR call it with smaller buffer sizes.

This program's output with ALSA when XX==16 (with alsa debug mode preventing
divide by zero):
   params: fragments=2 fragstotal=2 fragsize=32768 bytes=65536
Output with ALSA when XX==14:
   params: fragments=4 fragstotal=4 fragsize=16384 bytes=65536

Output with OSS when XX==16:
   fragments=4 fragstotal=4 fragsize=32768 bytes=131072
Output with OSS when XX==14:
   fragments=4 fragstotal=4 fragsize=16384 bytes=65536

Note that the bug has been observed when using an Ensoniq AudioPCI card with
the ens1370 ALSA driver.

I hope this is of assistance.
  jonathan

/*
 * This is a small program to illustrate a problem with the OSS emulation
 * in ALSA driver 1.0.2c.  The initialisation sequence herein causes
 * a divide by zero in snd_pcm_timer_resolution_change().  More particularly,
 * the SNDCTL_DSP_SETFRAGMENT ioctl call has a side effect which causes
 * the divide by zero when SNDCTL_DSP_SETFMT is called.
 *
 * buffer_info = (4 << 16) | XX;
 * If XX is 16 the fault is triggered.  If XX is 14 everything's fine.
 * In general, if XX<=14 everything works, but XX>=15 triggers the bug.
 *
 * Compile with
 *   gcc -o test_alsa_oss{,.c}
 *
 * The bug has been observed when using the ens1370 driver.  It's not known
 * whether it is triggered with other soundcards/drivers.
 *
 * Note: Cinelerra's default configuration has 16384 samples in the buffer -
 * this makes XX equal to 16, thus triggering the bug.
 *
 */
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>

int set_cloexec_flag(int desc, int value) {
  int oldflags = fcntl (desc, F_GETFD, 0);
  if (oldflags < 0) return oldflags;
  if(value != 0)
    oldflags |= FD_CLOEXEC;
  else
    oldflags &= ~FD_CLOEXEC;
  return fcntl(desc, F_SETFD, oldflags);
}

int main() {

int fd;
int format = AFMT_S16_LE;
int buffer_info = (4 << 16) | 16;
int res, arg;
audio_buf_info playinfo;

  fd = open("/dev/dsp", O_WRONLY);
  if (fd<1) {
    fprintf(stderr,"open() failed on /dev/dsp\n");
    return 1;
  } else {
    printf("open(): fd = %d\n",fd);
  }

  if (set_cloexec_flag(fd,1)<0) {
    printf("failed to set close-on-exec flag\n");
  }

  res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &buffer_info);
  if (res < 0)
    printf("SNDCTL_DSP_SETFRAGMENT failed: returned %d\n",res);
  else
    printf("SNDCTL_DSP_SETFRAGMENT ok: %d\n",res); 
  res = ioctl(fd, SNDCTL_DSP_SETFMT, &format);
  if (res < 0)
    printf("SNDCTL_DSP_SETFMT failed: returned %d\n",res);
  else
    printf("SNDCTL_DSP_SETFMT ok: %d\n",res);
   
  arg = 2;
  res = ioctl(fd, SNDCTL_DSP_CHANNELS, &arg);
  if (res < 0)
    printf("SNDCTL_DSP_CHANNELS failed: returned %d\n",res);
  else
    printf("SNDCTL_DSP_CHANNELS ok: %d\n",res);
  arg = 48000;
  res = ioctl(fd, SNDCTL_DSP_SPEED, &arg);
  if (res < 0)
    printf("SNDCTL_DSP_SPEED failed: returned %d\n",res);
  else
    printf("SNDCTL_DSP_SPEED ok: %d\n",res);

  ioctl(fd, SNDCTL_DSP_GETOSPACE, &playinfo);
  printf("params: fragments=%d fragstotal=%d fragsize=%d bytes=%d\n",
    playinfo.fragments, playinfo.fragstotal, playinfo.fragsize, 
    playinfo.bytes);

  close(fd);
  return 0;
}

-- 
* Jonathan Woithe    jwoithe@physics.adelaide.edu.au                        *
*                    http://www.physics.adelaide.edu.au/~jwoithe            *
***-----------------------------------------------------------------------***
** "Time is an illusion; lunchtime doubly so"                              **
*  "...you wouldn't recognize a subtle plan if it painted itself purple and *
*   danced naked on a harpsichord singing 'subtle plans are here again'"    *


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ALSA driver 1.0.2c: divide by zero oops
  2004-03-23  5:51           ` Jonathan Woithe
@ 2004-03-23  8:49             ` Jaroslav Kysela
  0 siblings, 0 replies; 8+ messages in thread
From: Jaroslav Kysela @ 2004-03-23  8:49 UTC (permalink / raw)
  To: Jonathan Woithe; +Cc: Takashi Iwai, alsa-devel

On Tue, 23 Mar 2004, Jonathan Woithe wrote:

> > Could you add exactly same initialization sequence to 
> > alsa-oss/test/testoss.c code? So we can debug easily the problem here.
> 
> Sorry, I couldn't see where this would fit in in this file - testoss.c seems
> more like it's testing the oss redirector though.  The bug I'm seeing is in
> software which uses the oss emulation layer directly (that is, it accesses
> /dev/dsp with no knowledge of ALSA).

This code uses also directly the OSS layer.

> This program's output with ALSA when XX==16 (with alsa debug mode preventing
> divide by zero):
>    params: fragments=2 fragstotal=2 fragsize=32768 bytes=65536

The reason for oops is simple: The period is too much big to store 
resolution in the 32-bit value. The bellow patch fixed the oops, but
it's still not perfect solution (PCM slave timer resolution will be broken 
in this case):


Index: pcm_timer.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/pcm_timer.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- pcm_timer.c	13 Aug 2002 16:13:34 -0000	1.6
+++ pcm_timer.c	23 Mar 2004 08:37:09 -0000	1.7
@@ -32,9 +32,9 @@
  */
 
 /* Greatest common divisor */
-static int gcd(int a, int b)
+static unsigned long gcd(unsigned long a, unsigned long b)
 {
-	int r;
+	unsigned long r;
 	if (a < b) {
 		r = a;
 		a = b;
@@ -49,7 +49,7 @@
 
 void snd_pcm_timer_resolution_change(snd_pcm_substream_t *substream)
 {
-	unsigned int rate, mult, fsize, l;
+	unsigned long rate, mult, fsize, l;
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	
         mult = 1000000000;
@@ -67,7 +67,11 @@
 		mult /= 2;
 		rate /= 2;
 	}
-	snd_assert(rate != 0, return);
+	if (rate == 0) {
+		snd_printk(KERN_ERR "pcm timer resolution out of range (rate = %u, period_size = %lu)\n", runtime->rate, runtime->period_size);
+		runtime->timer_resolution = -1;
+		return;
+	}
 	runtime->timer_resolution = mult * fsize / rate;
 }
 

						Jaroslav

-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs


-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2004-03-23  8:49 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-14 23:17 ALSA driver 1.0.2c: divide by zero oops Jonathan Woithe
2004-03-15 10:44 ` Takashi Iwai
2004-03-15 22:15   ` Jonathan Woithe
2004-03-16 10:40     ` Takashi Iwai
2004-03-17 22:30       ` Jonathan Woithe
2004-03-18  8:58         ` Jaroslav Kysela
2004-03-23  5:51           ` Jonathan Woithe
2004-03-23  8:49             ` Jaroslav Kysela

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.