Bug#584605: audacity: Continuing to backtrace

Dave Witbrodt dawitbro at sbcglobal.net
Sun Jun 13 22:11:08 UTC 2010


Package: audacity
Version: 1.3.12-3+fix03
Severity: normal


Forgive the version listed above:  it is from my local build, and is obviously
not an official Debian package.

After applying the patch suggested, I was getting a FTBFS:
----------

[...]
g++ -c -g -O2 -g -Wall -O2 -I../lib-src/portmixer/include -I../lib-src/portaudio-v19/include -g -O2 -g -Wall -O2  -Wall -I/usr/lib/wx/include/gtk2-unicode-release-2.8 -I/usr/include/wx-2.8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -D__WXGTK__ -pthread -I../lib-src/FileDialog -g -O2 -Wall -I/home/dawitbro/sandbox/audacity/audacity-1.3.12/lib-src/lib-widget-extra            -I../lib-src/sbsms/include -I/usr/include/soundtouch   -I../lib-src/libnyquist          -g -O2 -Wall -I/home/dawitbro/sandbox/audacity/audacity-1.3.12/lib-src/portsmf    -fno-strict-aliasing -I./include -I. -DLIBDIR=\"/usr/lib\" -D__STDC_CONSTANT_MACROS   -Wall -pthread -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12     FFmpeg.cpp -o FFmpeg.o
FFmpeg.cpp:257: error: invalid conversion from ‘int (*)(URLContext*, unsigned char*, int)’ to ‘int (*)(URLContext*, const unsigned char*, int)’
make[2]: *** [FFmpeg.o] Error 1
make[2]: Leaving directory `/home/dawitbro/sandbox/audacity/audacity-1.3.12/src'
make[1]: *** [audacity] Error 2
make[1]: Leaving directory `/home/dawitbro/sandbox/audacity/audacity-1.3.12'
make: *** [debian/stamp-makefile-build] Error 2
dpkg-buildpackage: error: debian/rules build gave error exit status 2
----------


The error was indicating the closing brace of this block of code:

    $ grep -n -A 7 "URLProtocol ufile_protocol" src/FFmpeg.cpp 
    250:URLProtocol ufile_protocol = {
    251-    "ufile",
    252-    ufile_open,
    253-    ufile_read,
    254-    ufile_write,
    255-    ufile_seek,
    256-    ufile_close,
    257-};

Clearly there was some sort of type mismatch, so I looked around for
a while.  I thought I had found the definition of "URLProtocol" here:

    $ grep -A 12 "typedef struct URLProtocol" lib-src/ffmpeg/libavformat/avio.h 
    typedef struct URLProtocol {
	const char *name;
	int (*url_open)(URLContext *h, const char *filename, int flags);
	int (*url_read)(URLContext *h, unsigned char *buf, int size);
	int (*url_write)(URLContext *h, unsigned char *buf, int size);
	int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
	int (*url_close)(URLContext *h);
	struct URLProtocol *next;
	int (*url_read_pause)(URLContext *h, int pause);
	int64_t (*url_read_seek)(URLContext *h, int stream_index,
				 int64_t timestamp, int flags);
	int (*url_get_file_handle)(URLContext *h);
    } URLProtocol;

And the prototypes which might match the 'make' error above are "url_open",
"url_read", and "url_write"; these correspond to ufile_open(), ufile_read(),
and ufile_write() in src/FFmpeg.cpp:

    $ egrep -n 'int ufile_(open|read|write)' src/FFmpeg.cpp
    170:static int ufile_open(URLContext *h, const char *filename, int flags)
    198:static int ufile_read(URLContext *h, unsigned char *buf, int size)
    207:static int ufile_write(URLContext *h, unsigned char *buf, int size)

I couldn't SEE any problem to cause 'make' to fail here.  After about an hour
it dawned on me that 'audacity' seems to be shipping its own FFMPEG code, but
that the Debian sources for 'audacity' build-depend on an external FFMPEG.


***************
*** WARNING ***
The following discussion must be understood in the context of the packages
on my system.  I believe that I am using FFMPEG from debian-multimedia.org:

    $ apt-cache policy libavformat52
    libavformat52:
      Installed: 5:0.6~svn20100603-0.0
      Candidate: 5:0.6~svn20100603-0.0
      Version table:
     *** 5:0.6~svn20100603-0.0 0
	    990 http://mirror.csclub.uwaterloo.ca unstable/main Packages
	    100 /var/lib/dpkg/status
	 4:0.6~svn20100505-1 0
	    350 http://debian.osuosl.org experimental/main Packages
	 4:0.5.2-1 0
	    990 http://debian.osuosl.org unstable/main Packages

If this is a critical issue in terms of dealing with this bug, please let
me know what changes to make in my local builds, or whether to cancel the
bug report entirely.  So far, I am seeing evidence of real bugs in the
audacity source code, before external FFMPEG libraries are even involved.
*** END WARNING ***
*******************


Once I realized that the build was being made against the external FFMPEG,
I looked around at the listing of build dependencies and eventually
discovered this:

    $ grep -Rn -A 12 "typedef struct URLProtocol" /usr/include/libavformat/avio.h 
    223:typedef struct URLProtocol {
    224-    const char *name;
    225-    int (*url_open)(URLContext *h, const char *url, int flags);
    226-    int (*url_read)(URLContext *h, unsigned char *buf, int size);
    227-    int (*url_write)(URLContext *h, const unsigned char *buf, int size);
    228-    int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);
    229-    int (*url_close)(URLContext *h);
    230-    struct URLProtocol *next;
    231-    int (*url_read_pause)(URLContext *h, int pause);
    232-    int64_t (*url_read_seek)(URLContext *h, int stream_index,
    233-                             int64_t timestamp, int flags);
    234-    int (*url_get_file_handle)(URLContext *h);
    235-} URLProtocol;

Compare line 227 here with the corresponding "url_write" line above, and
you will see that the external FFMPEG library has added "const" to the
second argument.

I patched my local 'audacity' sources this way:
----------

$ cat fix-ufile_write-definition.patch
--- a/src/FFmpeg.cpp	2010-06-13 15:28:16.000000000 -0400
+++ b/src/FFmpeg.cpp	2010-06-13 15:56:16.000000000 -0400
@@ -204,7 +204,7 @@
    return ret;
 }
 
-static int ufile_write(URLContext *h, unsigned char *buf, int size)
+static int ufile_write(URLContext *h, const unsigned char *buf, int size)
 {
    return (int) ((wxFile *) h->priv_data)->Write(buf, size);
 }
----------


The build succeed after that.

Unfortunately, 'audacity' was still having problems after trying to run
the locally patched version:
----------

(gdb) bt
#0  0x00007ffff2865166 in ?? () from /lib/libc.so.6
#1  0x00007ffff37a1630 in snd_mixer_find_selem () from /usr/lib/libasound.so.2
#2  0x000000000085e656 in open_mixer (dev=0xfc9990, card=<value optimized out>, playback=<value optimized out>) at src/px_linux_alsa.c:180
#3  0x000000000085ea77 in OpenMixer_Linux_ALSA (Px=0xfc7d50, index=<value optimized out>) at src/px_linux_alsa.c:296
#4  0x000000000085d1e3 in Px_OpenMixer (pa_stream=0xfc6ba0, i=0) at src/px_mixer.c:155
#5  0x000000000051d23f in AudioIO::HandleDeviceChange (this=0xe86130) at AudioIO.cpp:573
#6  0x000000000051d774 in AudioIO (this=0xe86130) at AudioIO.cpp:351
#7  0x000000000051d874 in InitAudioIO () at AudioIO.cpp:216
#8  0x0000000000517342 in AudacityApp::OnInit (this=0xddb2c0) at AudacityApp.cpp:1057
#9  0x00007ffff6d1c632 in wxEntry(int&, wchar_t**) () from /usr/lib/libwx_baseu-2.8.so.0
#10 0x0000000000512f02 in main (argc=1, argv=0x7fffffffdb10) at AudacityApp.cpp:626
----------

It is now failing at a different location in the same file:
lib-src/portmixer/src/px_linux_alsa.c

This is the section of the function open_mixer() where the program dies:
----------

static int open_mixer(PxDev *dev, int card, int playback)
{
   [...]

      i = 0;
      for (elem = snd_mixer_first_elem(dev->handle);
           elem != NULL;
           elem = snd_mixer_elem_next(elem))
      {
         snd_mixer_elem_t *vol;
         int ndx;

         if (playback) {
            if (snd_mixer_selem_has_common_volume(elem) ||
                snd_mixer_selem_has_playback_volume(elem)) {
               snprintf(name,
                        sizeof(name),
                        "%s:%d",
                        snd_mixer_selem_get_name(elem),
                        snd_mixer_selem_get_index(elem));
      
               dev->selems[i].elem = elem;
               dev->selems[i].index = snd_mixer_selem_get_index(elem);
               dev->selems[i].name = strdup(name);
               if (!dev->selems[i].name) {
                  break;
               }
               i++;
            }
            continue;
         }

         snd_mixer_selem_id_set_name(sid, "Capture");
         snd_mixer_selem_id_set_index(sid, snd_mixer_selem_get_index(elem));
*        vol = snd_mixer_find_selem(dev->handle, sid);

         [...]
----------

Line 180, where the segfault occurs, is the last line printed here, the
call to snd_mixer_find_selem() [marked with *].  We have arrived here
from line 296 of the same file [marked with * below]:
----------

    int OpenMixer_Linux_ALSA(px_mixer *Px, int index)
    {
       PxInfo *info;
       int card;

       if (!initialize(Px)) {
	  return FALSE;
       }

       info = (PxInfo *) Px->info;

       if (PaAlsa_GetStreamInputCard(Px->pa_stream, &card) == paNoError) {
*	  if (!open_mixer(&info->capture, card, FALSE)) {
	     return cleanup(Px);
	  }
       }

       if (PaAlsa_GetStreamOutputCard(Px->pa_stream, &card) == paNoError) {
	  if (!open_mixer(&info->playback, card, TRUE)) {
	     return cleanup(Px);
	  }
       }

       return TRUE;
    }
----------

Reviewing, it looks like OpenMixer_Linux_ALSA() calls open_mixer() with an
address where information can be stored, a card #, and a third argument of
FALSE (which apparently corresponds to Capture instead of Playback devices).

Once inside open_mixer(), the function runs until it arrives at the "for"
loop reproduced above.  The value of "i" is set to 0, the "if (playback)"
block is skipped ("playback" was the 3rd parameter of the function, which
was called with FALSE), and we hit these lines ...

         snd_mixer_selem_id_set_name(sid, "Capture");
         snd_mixer_selem_id_set_index(sid, snd_mixer_selem_get_index(elem));
         vol = snd_mixer_find_selem(dev->handle, sid);

... where the segfault occurs.  Something else is puzzling me now, and it has
to do with the value of "i".  The full backtrace looks like this:
----------

(gdb) bt full
#0  0x00007ffff2865166 in ?? () from /lib/libc.so.6
No symbol table info available.
#1  0x00007ffff37a1630 in snd_mixer_find_selem () from /usr/lib/libasound.so.2
No symbol table info available.
#2  0x000000000085e656 in open_mixer (dev=0xfc9990, card=<value optimized out>, playback=<value optimized out>) at src/px_linux_alsa.c:180
        vol = 0x0
        err = <value optimized out>
        i = 530
        elem = 0xfea050
        name = "DSP 31:0\000F Right:0\000\000\000\000\000\000\242\001\205\000\000\000\000\000\001\000\000\000\000\000\000\000\003", '\000' <repeats 15 times>"\254, \003\000\000\000\000\000\000\001\000\000\000\377\177\000\000@\232Q", '\000' <repeats 13 times>"\220, \336\377\377\377\177\000\000\240n\374\000\000\000\000\000\000\000\000\000\200\210\345@\001\000\000\000\001\000\000\000\001\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000`\000\000\000\000\000\000\000p\335\377\377\377\177\000\000\250~\264\362\377\177\000\000H\263g\256\031Τ?P\000\000\000\000\000\000\000\260\335\377\377\006\000\000\000h~\264\362\377\177\000\000\003\000\000\000\000\000\000\000\360\000\000\000\000\000\000\000\230~\264\362\377\177\000\000P}\374\000\000\000\000\000PJ\002\000\000\000\000\000\260\325\375\000\000\000\000\000P\000\000\000\000\000\000\000J\252\204\000\000\000\000"
#3  0x000000000085ea77 in OpenMixer_Linux_ALSA (Px=0xfc7d50, index=<value optimized out>) at src/px_linux_alsa.c:296
        card = 0
#4  0x000000000085d1e3 in Px_OpenMixer (pa_stream=0xfc6ba0, i=0) at src/px_mixer.c:155
        good = <value optimized out>
#5  0x000000000051d23f in AudioIO::HandleDeviceChange (this=0xe86130) at AudioIO.cpp:573
        recDeviceNum = <value optimized out>
        stream = 0xfc6ba0
        playDeviceNum = <value optimized out>
        numrates = <value optimized out>
        highestSampleRate = <value optimized out>
        error = 0
        playbackParameters = {device = 26, channelCount = 1, sampleFormat = 1, suggestedLatency = 0.042653061224489794, hostApiSpecificStreamInfo = 0x0}
        captureParameters = {device = 0, channelCount = 1, sampleFormat = 1, suggestedLatency = 0.011609977324263039, hostApiSpecificStreamInfo = 0x0}
        inputVol = 0
#6  0x000000000051d774 in AudioIO (this=0xe86130) at AudioIO.cpp:351
        err = <value optimized out>
#7  0x000000000051d874 in InitAudioIO () at AudioIO.cpp:216
No locals.
#8  0x0000000000517342 in AudacityApp::OnInit (this=0xddb2c0) at AudacityApp.cpp:1057
        future1 = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xde9a18 L"Master Gain Control"}, <No data fields>}
        lang = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xe878e8 L"en"}, <No data fields>}
        pWnd = <value optimized out>
        appName = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xde9938 L"audacity"}, <No data fields>}
        future2 = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xddb748 L"Input Meter"}, <No data fields>}
        home = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xdeb118 L"/home/dawitbro"}, <No data fields>}
        pathVar = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0x7ffff6d98678 L""}, <No data fields>}
        tmpFile = {m_volume = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0x7ffff6d98678 L""}, <No data fields>}, m_dirs = {m_nSize = 16, m_nCount = 1, m_pItems = 0xe82610, 
            m_autoSort = false}, m_name = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xe81bf8 L"nnHRM19Y"}, <No data fields>}, m_ext = {<wxStringBase> = {
              static npos = 18446744073709551615, m_pchData = 0x7ffff6d98678 L""}, <No data fields>}, m_relative = false, m_hasExt = false}
        project = <value optimized out>
        vendorName = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xde99a8 L"audacity"}, <No data fields>}
        future3 = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xde9ac8 L"Output Meter"}, <No data fields>}
        tmpDirLoc = {<wxStringBase> = {static npos = 18446744073709551615, m_pchData = 0xe81cf8 L"/tmp"}, <No data fields>}
        didRecoverAnything = <value optimized out>
#9  0x00007ffff6d1c632 in wxEntry(int&, wchar_t**) () from /usr/lib/libwx_baseu-2.8.so.0
No symbol table info available.
#10 0x0000000000512f02 in main (argc=1, argv=0x7fffffffdb10) at AudacityApp.cpp:626
No locals.
----------

In stack frame #2, we clearly have a value of 530 in "i".  When did
that happen, since last we saw "i" was just set to 0?

This must mean that the "for" loop has iterated 529 times, and
dies the 530th time.  I'm not sure if that's bad or good.  Quite
frankly, I can't pretend to understand this code.  In my view,
open_mixer() ought to be rewritten using some helper functions
to decrease the size of the code.  However, I am also unfamiliar
with these ALSA library data structures and functions, so there
was never much chance I could understand it in the first place.

Hopefully someone on the Debian Multimedia Maintainers team can make
sense out of this, or it is headed upstream.

In case it helps, here is what 'aplay' detects for my hardware:

    $ aplay -l
    **** List of PLAYBACK Hardware Devices ****
    card 0: EMU0404 [E-mu 0404b PCI [MAEM8852]], device 0: emu10k1 [ADC Capture/Standard PCM Playback]
      Subdevices: 32/32
      Subdevice #0: subdevice #0
      Subdevice #1: subdevice #1
      Subdevice #2: subdevice #2
      Subdevice #3: subdevice #3
      Subdevice #4: subdevice #4
      Subdevice #5: subdevice #5
      Subdevice #6: subdevice #6
      Subdevice #7: subdevice #7
      Subdevice #8: subdevice #8
      Subdevice #9: subdevice #9
      Subdevice #10: subdevice #10
      Subdevice #11: subdevice #11
      Subdevice #12: subdevice #12
      Subdevice #13: subdevice #13
      Subdevice #14: subdevice #14
      Subdevice #15: subdevice #15
      Subdevice #16: subdevice #16
      Subdevice #17: subdevice #17
      Subdevice #18: subdevice #18
      Subdevice #19: subdevice #19
      Subdevice #20: subdevice #20
      Subdevice #21: subdevice #21
      Subdevice #22: subdevice #22
      Subdevice #23: subdevice #23
      Subdevice #24: subdevice #24
      Subdevice #25: subdevice #25
      Subdevice #26: subdevice #26
      Subdevice #27: subdevice #27
      Subdevice #28: subdevice #28
      Subdevice #29: subdevice #29
      Subdevice #30: subdevice #30
      Subdevice #31: subdevice #31
    card 0: EMU0404 [E-mu 0404b PCI [MAEM8852]], device 2: emu10k1 efx [Multichannel Capture/PT Playback]
      Subdevices: 8/8
      Subdevice #0: subdevice #0
      Subdevice #1: subdevice #1
      Subdevice #2: subdevice #2
      Subdevice #3: subdevice #3
      Subdevice #4: subdevice #4
      Subdevice #5: subdevice #5
      Subdevice #6: subdevice #6
      Subdevice #7: subdevice #7
    card 0: EMU0404 [E-mu 0404b PCI [MAEM8852]], device 3: emu10k1 [Multichannel Playback]
      Subdevices: 1/1
      Subdevice #0: subdevice #0
    card 1: SB [HDA ATI SB], device 0: ALC889 Analog [ALC889 Analog]
      Subdevices: 0/1
      Subdevice #0: subdevice #0
    card 1: SB [HDA ATI SB], device 1: ALC889 Digital [ALC889 Digital]
      Subdevices: 1/1
      Subdevice #0: subdevice #0
    card 2: HDMI [HDA ATI HDMI], device 3: ATI HDMI [ATI HDMI]
      Subdevices: 1/1
      Subdevice #0: subdevice #0

(At this point, it would be appropriate if someone could change the
title of this bug in the BTS, since the complaint about JACK not
running had nothing to do with the problem.  I don't know my way
around the BTS well enough, yet, to do that -- not even sure if I
have the permissions to do it.)


HTH,
Dave W.





More information about the pkg-multimedia-maintainers mailing list