Thread: [Audacity-devel] Debugging never-ending portaudio init
A free multi-track audio editor and recorder
Brought to you by:
aosiniao
From: Lasse S. B. <las...@gm...> - 2013-09-19 11:28:00
|
In short I see that the portaudio initialization never completes on my system, because it keeps looping around in a *while(1)* inside the function *GetConnectedPin(..)*. It keeps churning away on what to me seems like perfectly valid data. I haven't yet had the time to fully understand the functionality of the code (or the architecture), so I'm presenting my findings here - maybe somebody else will know what's going on precisely, so we can shortcut the learning curve... This will be a bit long. Skip half way down to "THE ONE THAT GOES BERSERK" if you feel confident this is obvious to you ;-) *THE ONE THAT'S OK:* First time inside GetConnectedPin(..) is OK. Called from pa_win_wdmks.c/PinNew(..) line 1563, right after this: PA_DEBUG(("PinNew: Finding topology pin...\n")); while(1) LOOP 0: FindStartConnectionFrom(..) gets this KSTOPOLOGY_CONNECTION record: {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin: 0} The validation in the line: if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == KSFILTER_NODE) is false because FromNode isn't KSFILTER_NODE. The validation in the line: if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) is false, because muxPosition==-1 while(1) LOOP 1: fnGetConnection(..) gets this record: {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin: 1} The validation in the line: if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == KSFILTER_NODE) is true, so: return forward ? conn->ToNodePin : conn->FromNodePin; is executed. Yay! So the return value is 1. It turns out this is a physical connection we found, so the PinNew(...) function continues at line 1627. It turns out the connection has this name: symbLinkName "\??\HDAUDIO#FUNC_01&VEN_10EC&DEV_0885&SUBSYS_106B3600&REV_1001#4&26c46e2&0&0001#{6994ad04-93ef-11d0-a3cc-00a0c9223196}\DigitalInputTopo" wchar_t [260] I have no idea whether this is meaningful or not. At least it doesn't appear to be cut off, as it is way shorter than 260 chars. This line is run: PA_DEBUG(("PinNew: Creating topology filter '%S'\n", symbLinkName)); This line is run: PA_DEBUG(("PinNew: Opening topology filter...")); This line is run: if (pin->dataFlow == KSPIN_DATAFLOW_IN) - but it passed for the *else* clause, as pin->dataFlow==KSPIN_DATAFLOW_OUT This line is run: PA_DEBUG(("PinNew: Checking for input endpoint pin id (%d)...\n", i)); And now we descend into the GetConnectedPin(..) that never completes. *THE ONE THAT GOES BERSERK*: GetConnectedPin(..) is now called from pa_win_wdmks.c/PinNew(..) line 1760. while(1) LOOP 0: FindStartConnectionFrom(..) gets this KSTOPOLOGY_CONNECTION record *again* : {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin: 0} The validation in the line: if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == KSFILTER_NODE) is false because FromNode isn't KSFILTER_NODE. *Again.* The validation in the line: if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) is true this time, because muxPosition==0 The validation line: if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) is true, so we continue to ULONG nConn = GetNumberOfConnectionsTo(conn, filter); which gets the value *1*, and conn = fnGetConnection(conn, filter, muxPosition); which gets the value of this record: {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin:1} The validation: if (muxInputPinId != 0) is false because muxInputPinId is indeed 0. The validation: if (muxNodeId != 0) is true because muxNodeId is indeed a valid pointer (note: Why don't they enter it as "if (muxNodeId != NULL)" ???? Would make it more obvious!) So the line: *muxNodeId = conn->ToNode; is executed, which sets *muxNodeId = *0* instead of the value -1 (aka KSFILTER_NODE) it had before. (note: This value is entered from PinNew(..) with the var name of "muxNodeId*Test*", so it's probably fine it's thrown away.) while(1) LOOP 1: conn = fnGetConnection(conn, filter, -1); returns this record: {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin:0} The validation: if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == KSFILTER_NODE) is false, because conn->FromNode is 0. The validation: if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) is true because muxPosition==0. The validation: if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) is true *again*, so we continue to ULONG nConn = GetNumberOfConnectionsTo(conn, filter); which gets the value *1, again*, and conn = fnGetConnection(conn, filter, muxPosition); which gets the value of this record: {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin:1} *again* The validation: if (muxInputPinId != 0) is false *again *because muxInputPinId is indeed 0. The validation: if (muxNodeId != 0) is true *again *because muxNodeId is indeed still a valid pointer So the line: *muxNodeId = conn->ToNode; is executed *again*, which sets *muxNodeId = *0* - which is the value it already had. while(1) LOOP 2 -> ∞: Same as LOOP 1. *CONCLUSION:* It seems my topology/architecture doesn't behave quite like the library expects - either it or the library doesn't follow the specifications 100%. There is no crash and nothing is obviously wrong, there's just an infinite loop, because of the way data is interpreted. *QUICK AND DIRTY FIX:* Replace the *while(1)* with something else. And then return an error value of some sort - not sure what that should be, as the PinNew(..) code below the calling point (line 1768) doesn't check for errors.We'd therefore have to alter the PinNew(..) code too. *A MORE ELABORATE QUICK FIX:* Keep track of the data from last iteration, and if the exact same data appears twice it is clear that we're hung. Again we'd have to think up a return value to signal error condition and a way to catch it in PinNew(..) *THE BEST AND MOST TIME CONSUMING FIX:* Find out *why* GetConnectedPin(..) gets stuck and fix it for real... RECOMMENDATION: I personally have lived and been contend with the latency of standard windows audio, and if I really wanted to do something more serious with Audacity I'd probably buy new hardware. So I recommend either of the quick fixes, and then an explanation aimed at those who really wanted the low-latency audio - a first-failure dialog for instance? // Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen |
From: Lasse S. B. <las...@gm...> - 2013-09-19 12:03:18
|
I just tested "QUICK AND DIRTY FIX" with *success*. Simply replacing the line: while(1) with this: long lTimeout = 1024; while(--lTimeout) means I run Audacity with no problems. I can even use the WDM-KS setting and both recording and playback works fine. Audacity loads in 4 seconds, which is quite normal on my system and is great considering I run Debug mode from within Visual Studio. I also tested what I called the "MORE ELABORATE QUICK FIX" - that one failed with an assertion, obviously because I did it wrong somehow.... ;) // Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen On Thu, Sep 19, 2013 at 1:27 PM, Lasse Steen Bohnstedt < las...@gm...> wrote: > In short I see that the portaudio initialization never completes on my > system, because it keeps looping around in a *while(1)* inside the > function *GetConnectedPin(..)*. > It keeps churning away on what to me seems like perfectly valid data. > I haven't yet had the time to fully understand the functionality of the > code (or the architecture), so I'm presenting my findings here - maybe > somebody else will know what's going on precisely, so we can shortcut the > learning curve... > > This will be a bit long. Skip half way down to "THE ONE THAT GOES BERSERK" > if you feel confident this is obvious to you ;-) > > *THE ONE THAT'S OK:* > First time inside GetConnectedPin(..) is OK. > Called from pa_win_wdmks.c/PinNew(..) line 1563, > right after this: PA_DEBUG(("PinNew: Finding topology pin...\n")); > while(1) LOOP 0: > FindStartConnectionFrom(..) gets this KSTOPOLOGY_CONNECTION record: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin: 0} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == > KSFILTER_NODE) > is false because FromNode isn't KSFILTER_NODE. > The validation in the line: > if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) > is false, because muxPosition==-1 > while(1) LOOP 1: > fnGetConnection(..) gets this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin: 1} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == > KSFILTER_NODE) > is true, so: > return forward ? conn->ToNodePin : conn->FromNodePin; > is executed. Yay! So the return value is 1. > > It turns out this is a physical connection we found, so the PinNew(...) > function continues at line 1627. It turns out the connection has this name: > > symbLinkName "\??\HDAUDIO#FUNC_01&VEN_10EC&DEV_0885&SUBSYS_106B3600&REV_1001#4&26c46e2&0&0001#{6994ad04-93ef-11d0-a3cc-00a0c9223196}\DigitalInputTopo" wchar_t > [260] > I have no idea whether this is meaningful or not. At least it doesn't > appear to be cut off, as it is way shorter than 260 chars. > This line is run: PA_DEBUG(("PinNew: Creating topology filter '%S'\n", > symbLinkName)); > This line is run: PA_DEBUG(("PinNew: Opening topology filter...")); > This line is run: if (pin->dataFlow == KSPIN_DATAFLOW_IN) - but it passed > for the *else* clause, as pin->dataFlow==KSPIN_DATAFLOW_OUT > This line is run: PA_DEBUG(("PinNew: Checking for input endpoint pin id > (%d)...\n", i)); > And now we descend into the GetConnectedPin(..) that never completes. > > *THE ONE THAT GOES BERSERK*: > GetConnectedPin(..) is now called from pa_win_wdmks.c/PinNew(..) line 1760. > while(1) LOOP 0: > FindStartConnectionFrom(..) gets this KSTOPOLOGY_CONNECTION record * > again*: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin: 0} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == > KSFILTER_NODE) > is false because FromNode isn't KSFILTER_NODE. *Again.* > The validation in the line: > if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) > is true this time, because muxPosition==0 > The validation line: > if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) > is true, so we continue to > ULONG nConn = GetNumberOfConnectionsTo(conn, filter); > which gets the value *1*, and > conn = fnGetConnection(conn, filter, muxPosition); > which gets the value of this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin:1} > The validation: if (muxInputPinId != 0) > is false because muxInputPinId is indeed 0. > The validation: if (muxNodeId != 0) > is true because muxNodeId is indeed a valid pointer (note: Why don't > they enter it as "if (muxNodeId != NULL)" ???? Would make it more obvious!) > So the line: *muxNodeId = conn->ToNode; > is executed, which sets *muxNodeId = *0* instead of the value -1 (aka > KSFILTER_NODE) it had before. > (note: This value is entered from PinNew(..) with the var name of > "muxNodeId*Test*", so it's probably fine it's thrown away.) > while(1) LOOP 1: > conn = fnGetConnection(conn, filter, -1); returns this record: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin:0} > The validation: if (forward ? conn->ToNode == KSFILTER_NODE : > conn->FromNode == KSFILTER_NODE) > is false, because conn->FromNode is 0. > The validation: if (filter->nodes->Count > 0 && !forward && muxPosition > >= 0) > is true because muxPosition==0. > The validation: if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) > is true *again*, so we continue to > ULONG nConn = GetNumberOfConnectionsTo(conn, filter); > which gets the value *1, again*, and > conn = fnGetConnection(conn, filter, muxPosition); > which gets the value of this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin:1} *again > * > The validation: if (muxInputPinId != 0) > is false *again *because muxInputPinId is indeed 0. > The validation: if (muxNodeId != 0) > is true *again *because muxNodeId is indeed still a valid pointer > So the line: *muxNodeId = conn->ToNode; > is executed *again*, which sets *muxNodeId = *0* - which is the value > it already had. > while(1) LOOP 2 -> ∞: > Same as LOOP 1. > > *CONCLUSION:* > It seems my topology/architecture doesn't behave quite like the library > expects - either it or the library doesn't follow the specifications 100%. > There is no crash and nothing is obviously wrong, there's just an infinite > loop, because of the way data is interpreted. > > *QUICK AND DIRTY FIX:* > Replace the *while(1)* with something else. > And then return an error value of some sort - not sure what that should > be, as the PinNew(..) code below the calling point (line 1768) doesn't > check for errors.We'd therefore have to alter the PinNew(..) code too. > > *A MORE ELABORATE QUICK FIX:* > Keep track of the data from last iteration, and if the exact same data > appears twice it is clear that we're hung. > Again we'd have to think up a return value to signal error condition and a > way to catch it in PinNew(..) > > *THE BEST AND MOST TIME CONSUMING FIX:* > Find out *why* GetConnectedPin(..) gets stuck and fix it for real... > > > RECOMMENDATION: > I personally have lived and been contend with the latency of standard > windows audio, and if I really wanted to do something more serious with > Audacity I'd probably buy new hardware. > So I recommend either of the quick fixes, and then an explanation aimed at > those who really wanted the low-latency audio - a first-failure dialog for > instance? > > // Lasse > > "There is a crack in everything, that's how the light gets in." - L. Cohen > |
From: Lasse S. B. <las...@gm...> - 2013-09-19 12:59:32
|
Actually I'll vote as such: +1 to quick and dirty fix - it is very quick to implement, it seems to work, and we don't have to know what's going on. Maybe the value should be higher than 1024. I have timed the Release version of 2.0.4 now, and it loads half a second faster than 2.0.3 for me (no idea why), so 1024 loops are not slowing things down in any way that can be measured on my (slow) system. -1 to "a more elaborate quick fix" - it wouldn't be enough to just quit if current and the latest values are equal; what if loops 1, 3, 5, etc.. were equal and 2, 4, 6, etc were equal? Or what if the pattern of re-occurrence was even more complex? It *could* be done, but it would be - well - elaborate. // Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen On Thu, Sep 19, 2013 at 2:02 PM, Lasse Steen Bohnstedt < las...@gm...> wrote: > I just tested "QUICK AND DIRTY FIX" with *success*. > Simply replacing the line: > while(1) > with this: > long lTimeout = 1024; while(--lTimeout) > means I run Audacity with no problems. I can even use the WDM-KS setting > and both recording and playback works fine. > Audacity loads in 4 seconds, which is quite normal on my system and is > great considering I run Debug mode from within Visual Studio. > > I also tested what I called the "MORE ELABORATE QUICK FIX" - that one > failed with an assertion, obviously because I did it wrong somehow.... ;) > > // Lasse > > "There is a crack in everything, that's how the light gets in." - L. Cohen > > > On Thu, Sep 19, 2013 at 1:27 PM, Lasse Steen Bohnstedt < > las...@gm...> wrote: > >> In short I see that the portaudio initialization never completes on my >> system, because it keeps looping around in a *while(1)* inside the >> function *GetConnectedPin(..)*. >> It keeps churning away on what to me seems like perfectly valid data. >> I haven't yet had the time to fully understand the functionality of the >> code (or the architecture), so I'm presenting my findings here - maybe >> somebody else will know what's going on precisely, so we can shortcut the >> learning curve... >> >> This will be a bit long. Skip half way down to "THE ONE THAT GOES >> BERSERK" if you feel confident this is obvious to you ;-) >> >> *THE ONE THAT'S OK:* >> First time inside GetConnectedPin(..) is OK. >> Called from pa_win_wdmks.c/PinNew(..) line 1563, >> right after this: PA_DEBUG(("PinNew: Finding topology pin...\n")); >> while(1) LOOP 0: >> FindStartConnectionFrom(..) gets this KSTOPOLOGY_CONNECTION record: >> {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin: 0} >> The validation in the line: >> if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == >> KSFILTER_NODE) >> is false because FromNode isn't KSFILTER_NODE. >> The validation in the line: >> if (filter->nodes->Count > 0 && !forward && muxPosition >= >> 0) >> is false, because muxPosition==-1 >> while(1) LOOP 1: >> fnGetConnection(..) gets this record: >> {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin: 1} >> The validation in the line: >> if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == >> KSFILTER_NODE) >> is true, so: >> return forward ? conn->ToNodePin : conn->FromNodePin; >> is executed. Yay! So the return value is 1. >> >> It turns out this is a physical connection we found, so the PinNew(...) >> function continues at line 1627. It turns out the connection has this name: >> >> symbLinkName "\??\HDAUDIO#FUNC_01&VEN_10EC&DEV_0885&SUBSYS_106B3600&REV_1001#4&26c46e2&0&0001#{6994ad04-93ef-11d0-a3cc-00a0c9223196}\DigitalInputTopo" wchar_t >> [260] >> I have no idea whether this is meaningful or not. At least it doesn't >> appear to be cut off, as it is way shorter than 260 chars. >> This line is run: PA_DEBUG(("PinNew: Creating topology filter '%S'\n", >> symbLinkName)); >> This line is run: PA_DEBUG(("PinNew: Opening topology filter...")); >> This line is run: if (pin->dataFlow == KSPIN_DATAFLOW_IN) - but it passed >> for the *else* clause, as pin->dataFlow==KSPIN_DATAFLOW_OUT >> This line is run: PA_DEBUG(("PinNew: Checking for input endpoint pin id >> (%d)...\n", i)); >> And now we descend into the GetConnectedPin(..) that never completes. >> >> *THE ONE THAT GOES BERSERK*: >> GetConnectedPin(..) is now called from pa_win_wdmks.c/PinNew(..) line >> 1760. >> while(1) LOOP 0: >> FindStartConnectionFrom(..) gets this KSTOPOLOGY_CONNECTION record * >> again*: >> {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin: 0} >> The validation in the line: >> if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == >> KSFILTER_NODE) >> is false because FromNode isn't KSFILTER_NODE. *Again.* >> The validation in the line: >> if (filter->nodes->Count > 0 && !forward && muxPosition >= >> 0) >> is true this time, because muxPosition==0 >> The validation line: >> if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) >> is true, so we continue to >> ULONG nConn = GetNumberOfConnectionsTo(conn, filter); >> which gets the value *1*, and >> conn = fnGetConnection(conn, filter, muxPosition); >> which gets the value of this record: >> {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin:1} >> The validation: if (muxInputPinId != 0) >> is false because muxInputPinId is indeed 0. >> The validation: if (muxNodeId != 0) >> is true because muxNodeId is indeed a valid pointer (note: Why don't >> they enter it as "if (muxNodeId != NULL)" ???? Would make it more obvious!) >> So the line: *muxNodeId = conn->ToNode; >> is executed, which sets *muxNodeId = *0* instead of the value -1 (aka >> KSFILTER_NODE) it had before. >> (note: This value is entered from PinNew(..) with the var name of >> "muxNodeId*Test*", so it's probably fine it's thrown away.) >> while(1) LOOP 1: >> conn = fnGetConnection(conn, filter, -1); returns this record: >> {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin:0} >> The validation: if (forward ? conn->ToNode == KSFILTER_NODE : >> conn->FromNode == KSFILTER_NODE) >> is false, because conn->FromNode is 0. >> The validation: if (filter->nodes->Count > 0 && !forward && muxPosition >> >= 0) >> is true because muxPosition==0. >> The validation: if (IsEqualGUID(&nodes[conn->FromNode], >> &KSNODETYPE_MUX)) >> is true *again*, so we continue to >> ULONG nConn = GetNumberOfConnectionsTo(conn, filter); >> which gets the value *1, again*, and >> conn = fnGetConnection(conn, filter, muxPosition); >> which gets the value of this record: >> {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin:1} * >> again* >> The validation: if (muxInputPinId != 0) >> is false *again *because muxInputPinId is indeed 0. >> The validation: if (muxNodeId != 0) >> is true *again *because muxNodeId is indeed still a valid pointer >> So the line: *muxNodeId = conn->ToNode; >> is executed *again*, which sets *muxNodeId = *0* - which is the value >> it already had. >> while(1) LOOP 2 -> ∞: >> Same as LOOP 1. >> >> *CONCLUSION:* >> It seems my topology/architecture doesn't behave quite like the library >> expects - either it or the library doesn't follow the specifications 100%. >> There is no crash and nothing is obviously wrong, there's just an >> infinite loop, because of the way data is interpreted. >> >> *QUICK AND DIRTY FIX:* >> Replace the *while(1)* with something else. >> And then return an error value of some sort - not sure what that should >> be, as the PinNew(..) code below the calling point (line 1768) doesn't >> check for errors.We'd therefore have to alter the PinNew(..) code too. >> >> *A MORE ELABORATE QUICK FIX:* >> Keep track of the data from last iteration, and if the exact same data >> appears twice it is clear that we're hung. >> Again we'd have to think up a return value to signal error condition and >> a way to catch it in PinNew(..) >> >> *THE BEST AND MOST TIME CONSUMING FIX:* >> Find out *why* GetConnectedPin(..) gets stuck and fix it for real... >> >> >> RECOMMENDATION: >> I personally have lived and been contend with the latency of standard >> windows audio, and if I really wanted to do something more serious with >> Audacity I'd probably buy new hardware. >> So I recommend either of the quick fixes, and then an explanation aimed >> at those who really wanted the low-latency audio - a first-failure dialog >> for instance? >> >> // Lasse >> >> "There is a crack in everything, that's how the light gets in." - L. Cohen >> > > |
From: Leland <le...@au...> - 2013-09-20 06:06:04
|
Hi Lasse, Can you replace GetConnectedPin with the following and give it a try? It's my "attempt" at actually detecting the loop. static ULONG GetConnectedPin(ULONG startPin, BOOL forward, PaWinWdmFilter* filter, int muxPosition, ULONG *muxInputPinId, ULONG *muxNodeId) { const KSTOPOLOGY_CONNECTION *conn = NULL; TFnGetConnection fnGetConnection = forward ? GetConnectionTo : GetConnectionFrom ; const KSTOPOLOGY_CONNECTION **seen = NULL; int seenndx, seencnt = 0; PA_LOGE_; seen = (KSTOPOLOGY_CONNECTION **)_alloca( sizeof(KSTOPOLOGY_CONNECTION *) * filter->connections->Count ); if( !seen ) { PA_DEBUG(("GetConnectedPin: Insufficient memory\n")); return KSFILTER_NODE; } while (1) { for (seenndx = 0; seenndx < seencnt; seenndx++) { if (seen[seenndx] == conn) { PA_DEBUG(("GetConnectedPin: Connection loop detected!\n")); return KSFILTER_NODE; } } if (conn == NULL) { conn = forward ? FindStartConnectionTo(startPin, filter) : FindStartConnectionFrom(startPin, filter); } else { conn = fnGetConnection(conn, filter, -1); } seen[seenndx++] = conn; /* Handling case of erroneous connection list */ if (conn == NULL) { break; } if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == KSFILTER_NODE) { return forward ? conn->ToNodePin : conn->FromNodePin; } else { PA_DEBUG(("GetConnectedPin: count=%d, forward=%d, muxPosition=%d\n", filter->nodes->Count, forward, muxPosition)); if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) { const GUID* nodes = (const GUID*)(filter->nodes + 1); if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) { ULONG nConn = GetNumberOfConnectionsTo(conn, filter); conn = fnGetConnection(conn, filter, muxPosition); if (conn == NULL) { break; } seen[seenndx++] = conn; if (muxInputPinId != 0) { *muxInputPinId = conn->ToNodePin; } if (muxNodeId != 0) { *muxNodeId = conn->ToNode; } } } } } PA_LOGL_; return KSFILTER_NODE; } Thanks much, Leland On 9/19/2013 7:58 AM, Lasse Steen Bohnstedt wrote: > Actually I'll vote as such: > > +1 to quick and dirty fix - it is very quick to implement, it seems to > work, and we don't have to know what's going on. Maybe the value > should be higher than 1024. I have timed the Release version of 2.0.4 > now, and it loads half a second faster than 2.0.3 for me (no idea > why), so 1024 loops are not slowing things down in any way that can be > measured on my (slow) system. > > -1 to "a more elaborate quick fix" - it wouldn't be enough to just > quit if current and the latest values are equal; what if loops 1, 3, > 5, etc.. were equal and 2, 4, 6, etc were equal? Or what if the > pattern of re-occurrence was even more complex? It *could* be done, > but it would be - well - elaborate. > > // Lasse > > "There is a crack in everything, that's how the light gets in." - L. Cohen > > > On Thu, Sep 19, 2013 at 2:02 PM, Lasse Steen Bohnstedt > <las...@gm... <mailto:las...@gm...>> > wrote: > > I just tested "QUICK AND DIRTY FIX" with *success*. > Simply replacing the line: > while(1) > with this: > long lTimeout = 1024; while(--lTimeout) > means I run Audacity with no problems. I can even use the WDM-KS > setting and both recording and playback works fine. > Audacity loads in 4 seconds, which is quite normal on my system > and is great considering I run Debug mode from within Visual Studio. > > I also tested what I called the "MORE ELABORATE QUICK FIX" - that > one failed with an assertion, obviously because I did it wrong > somehow.... ;) > > // Lasse > > "There is a crack in everything, that's how the light gets in." - > L. Cohen > > > On Thu, Sep 19, 2013 at 1:27 PM, Lasse Steen Bohnstedt > <las...@gm... > <mailto:las...@gm...>> wrote: > > In short I see that the portaudio initialization never > completes on my system, because it keeps looping around in a > *while(1)* inside the function *GetConnectedPin(..)*. > It keeps churning away on what to me seems like perfectly > valid data. > I haven't yet had the time to fully understand the > functionality of the code (or the architecture), so I'm > presenting my findings here - maybe somebody else will know > what's going on precisely, so we can shortcut the learning > curve... > > This will be a bit long. Skip half way down to "THE ONE THAT > GOES BERSERK" if you feel confident this is obvious to you ;-) > > _THE ONE THAT'S OK:_ > First time inside GetConnectedPin(..) is OK. > Called from pa_win_wdmks.c/PinNew(..) line 1563, > right after this: PA_DEBUG(("PinNew: Finding topology > pin...\n")); > while(1) LOOP 0: > FindStartConnectionFrom(..) gets > this KSTOPOLOGY_CONNECTION record: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; > ToNodePin: 0} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : > conn->FromNode == KSFILTER_NODE) > is false because FromNode isn't KSFILTER_NODE. > The validation in the line: > if (filter->nodes->Count > 0 && !forward && > muxPosition >= 0) > is false, because muxPosition==-1 > while(1) LOOP 1: > fnGetConnection(..) gets this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; > ToNodePin: 1} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : > conn->FromNode == KSFILTER_NODE) > is true, so: > return forward ? conn->ToNodePin : conn->FromNodePin; > is executed. Yay! So the return value is 1. > > It turns out this is a physical connection we found, so the > PinNew(...) function continues at line 1627. It turns out the > connection has this name: > symbLinkName "\??\HDAUDIO#FUNC_01&VEN_10EC&DEV_0885&SUBSYS_106B3600&REV_1001#4&26c46e2&0&0001#{6994ad04-93ef-11d0-a3cc-00a0c9223196}\DigitalInputTopo"wchar_t > [260] > I have no idea whether this is meaningful or not. At least it > doesn't appear to be cut off, as it is way shorter than 260 chars. > This line is run: PA_DEBUG(("PinNew: Creating topology filter > '%S'\n", symbLinkName)); > This line is run: PA_DEBUG(("PinNew: Opening topology > filter...")); > This line is run: if (pin->dataFlow == KSPIN_DATAFLOW_IN) - > but it passed for the *else* clause, as > pin->dataFlow==KSPIN_DATAFLOW_OUT > This line is run: PA_DEBUG(("PinNew: Checking for input > endpoint pin id (%d)...\n", i)); > And now we descend into the GetConnectedPin(..) that never > completes. > > _THE ONE THAT GOES BERSERK_: > GetConnectedPin(..) is now called from > pa_win_wdmks.c/PinNew(..) line 1760. > while(1) LOOP 0: > FindStartConnectionFrom(..) gets > this KSTOPOLOGY_CONNECTION record *again*: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; > ToNodePin: 0} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : > conn->FromNode == KSFILTER_NODE) > is false because FromNode isn't KSFILTER_NODE. *Again.* > The validation in the line: > if (filter->nodes->Count > 0 && !forward && > muxPosition >= 0) > is true this time, because muxPosition==0 > The validation line: > if (IsEqualGUID(&nodes[conn->FromNode], > &KSNODETYPE_MUX)) > is true, so we continue to > ULONG nConn = GetNumberOfConnectionsTo(conn, filter); > which gets the value *1*, and > conn = fnGetConnection(conn, filter, muxPosition); > which gets the value of this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; > ToNodePin:1} > The validation: if (muxInputPinId != 0) > is false because muxInputPinId is indeed 0. > The validation: if (muxNodeId != 0) > is true because muxNodeId is indeed a valid pointer (note: > Why don't they enter it as "if (muxNodeId != NULL)" ???? Would > make it more obvious!) > So the line: *muxNodeId = conn->ToNode; > is executed, which sets *muxNodeId = *0* instead of the > value -1 (aka KSFILTER_NODE) it had before. > (note: This value is entered from PinNew(..) with the var > name of "muxNodeId*Test*", so it's probably fine it's thrown > away.) > while(1) LOOP 1: > conn = fnGetConnection(conn, filter, -1); returns this record: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; > ToNodePin:0} > The validation: if (forward ? conn->ToNode == KSFILTER_NODE > : conn->FromNode == KSFILTER_NODE) > is false, because conn->FromNode is 0. > The validation: if (filter->nodes->Count > 0 && !forward && > muxPosition >= 0) > is true because muxPosition==0. > The validation: if (IsEqualGUID(&nodes[conn->FromNode], > &KSNODETYPE_MUX)) > is true *again*, so we continue to > ULONG nConn = GetNumberOfConnectionsTo(conn, filter); > which gets the value *1, again*, and > conn = fnGetConnection(conn, filter, muxPosition); > which gets the value of this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; > ToNodePin:1} *again* > The validation: if (muxInputPinId != 0) > is false *again *because muxInputPinId is indeed 0. > The validation: if (muxNodeId != 0) > is true *again *because muxNodeId is indeed still a valid > pointer > So the line: *muxNodeId = conn->ToNode; > is executed *again*, which sets *muxNodeId = *0* - which is > the value it already had. > while(1) LOOP 2 -> ?: > Same as LOOP 1. > > _CONCLUSION:_ > It seems my topology/architecture doesn't behave quite like > the library expects - either it or the library doesn't follow > the specifications 100%. > There is no crash and nothing is obviously wrong, there's just > an infinite loop, because of the way data is interpreted. > > _QUICK AND DIRTY FIX:_ > Replace the *while(1)* with something else. > And then return an error value of some sort - not sure what > that should be, as the PinNew(..) code below the calling point > (line 1768) doesn't check for errors.We'd therefore have to > alter the PinNew(..) code too. > > _A MORE ELABORATE QUICK FIX:_ > Keep track of the data from last iteration, and if the exact > same data appears twice it is clear that we're hung. > Again we'd have to think up a return value to signal error > condition and a way to catch it in PinNew(..) > > _THE BEST AND MOST TIME CONSUMING FIX:_ > Find out *why* GetConnectedPin(..) gets stuck and fix it for > real... > > > RECOMMENDATION: > I personally have lived and been contend with the latency of > standard windows audio, and if I really wanted to do something > more serious with Audacity I'd probably buy new hardware. > So I recommend either of the quick fixes, and then an > explanation aimed at those who really wanted the low-latency > audio - a first-failure dialog for instance? > > // Lasse > > "There is a crack in everything, that's how the light gets > in." - L. Cohen > > > > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > > > _______________________________________________ > audacity-devel mailing list > aud...@li... > https://lists.sourceforge.net/lists/listinfo/audacity-devel |
From: Gale A. <ga...@au...> - 2013-09-19 21:46:31
Attachments:
xp_hang_fixed_logs.zip
|
| From Lasse Steen Bohnstedt <las...@gm...> | Thu, 19 Sep 2013 14:02:38 +0200 | Subject: [Audacity-devel] Debugging never-ending portaudio init > I just tested "QUICK AND DIRTY FIX" with *success*. > Simply replacing the line: > while(1) > with this: > long lTimeout = 1024; while(--lTimeout) > means I run Audacity with no problems. I can even use the WDM-KS setting > and both recording and playback works fine. > Audacity loads in 4 seconds, which is quite normal on my system and is > great considering I run Debug mode from within Visual Studio. > > I also tested what I called the "MORE ELABORATE QUICK FIX" - that one > failed with an assertion, obviously because I did it wrong somehow.... ;) > > // Lasse Hi, I've been getting some feedback now from Leland's build that writes a debugging log file (and I think has some fixes to work around loops). That build has solved the XP hang in the two cases tested so far. WDM-KS loads, though one report suggests MME and WASAPI are missing - I'm awaiting clarification). I've attached the log files from these two cases. That build does nothing for BSOD's either on XP or Windows 7, and there is usually no log file produced in BSOD cases. I'll write to Leland off-list about that. Gale > On Thu, Sep 19, 2013 at 1:27 PM, Lasse Steen Bohnstedt < > las...@gm...> wrote: > > > In short I see that the portaudio initialization never completes on my > > system, because it keeps looping around in a *while(1)* inside the > > function *GetConnectedPin(..)*. > > It keeps churning away on what to me seems like perfectly valid data. > > I haven't yet had the time to fully understand the functionality of the > > code (or the architecture), so I'm presenting my findings here - maybe > > somebody else will know what's going on precisely, so we can shortcut the > > learning curve... > > > > This will be a bit long. Skip half way down to "THE ONE THAT GOES BERSERK" > > if you feel confident this is obvious to you ;-) > > > > *THE ONE THAT'S OK:* > > First time inside GetConnectedPin(..) is OK. > > Called from pa_win_wdmks.c/PinNew(..) line 1563, > > right after this: PA_DEBUG(("PinNew: Finding topology pin...\n")); > > while(1) LOOP 0: > > FindStartConnectionFrom(..) gets this KSTOPOLOGY_CONNECTION record: > > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin: 0} > > The validation in the line: > > if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == > > KSFILTER_NODE) > > is false because FromNode isn't KSFILTER_NODE. > > The validation in the line: > > if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) > > is false, because muxPosition==-1 > > while(1) LOOP 1: > > fnGetConnection(..) gets this record: > > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin: 1} > > The validation in the line: > > if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == > > KSFILTER_NODE) > > is true, so: > > return forward ? conn->ToNodePin : conn->FromNodePin; > > is executed. Yay! So the return value is 1. > > > > It turns out this is a physical connection we found, so the PinNew(...) > > function continues at line 1627. It turns out the connection has this name: > > > > symbLinkName "\??\HDAUDIO#FUNC_01&VEN_10EC&DEV_0885&SUBSYS_106B3600&REV_1001#4&26c46e2&0&0001#{6994ad04-93ef-11d0-a3cc-00a0c9223196}\DigitalInputTopo" wchar_t > > [260] > > I have no idea whether this is meaningful or not. At least it doesn't > > appear to be cut off, as it is way shorter than 260 chars. > > This line is run: PA_DEBUG(("PinNew: Creating topology filter '%S'\n", > > symbLinkName)); > > This line is run: PA_DEBUG(("PinNew: Opening topology filter...")); > > This line is run: if (pin->dataFlow == KSPIN_DATAFLOW_IN) - but it passed > > for the *else* clause, as pin->dataFlow==KSPIN_DATAFLOW_OUT > > This line is run: PA_DEBUG(("PinNew: Checking for input endpoint pin id > > (%d)...\n", i)); > > And now we descend into the GetConnectedPin(..) that never completes. > > > > *THE ONE THAT GOES BERSERK*: > > GetConnectedPin(..) is now called from pa_win_wdmks.c/PinNew(..) line 1760. > > while(1) LOOP 0: > > FindStartConnectionFrom(..) gets this KSTOPOLOGY_CONNECTION record * > > again*: > > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin: 0} > > The validation in the line: > > if (forward ? conn->ToNode == KSFILTER_NODE : conn->FromNode == > > KSFILTER_NODE) > > is false because FromNode isn't KSFILTER_NODE. *Again.* > > The validation in the line: > > if (filter->nodes->Count > 0 && !forward && muxPosition >= 0) > > is true this time, because muxPosition==0 > > The validation line: > > if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) > > is true, so we continue to > > ULONG nConn = GetNumberOfConnectionsTo(conn, filter); > > which gets the value *1*, and > > conn = fnGetConnection(conn, filter, muxPosition); > > which gets the value of this record: > > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin:1} > > The validation: if (muxInputPinId != 0) > > is false because muxInputPinId is indeed 0. > > The validation: if (muxNodeId != 0) > > is true because muxNodeId is indeed a valid pointer (note: Why don't > > they enter it as "if (muxNodeId != NULL)" ???? Would make it more obvious!) > > So the line: *muxNodeId = conn->ToNode; > > is executed, which sets *muxNodeId = *0* instead of the value -1 (aka > > KSFILTER_NODE) it had before. > > (note: This value is entered from PinNew(..) with the var name of > > "muxNodeId*Test*", so it's probably fine it's thrown away.) > > while(1) LOOP 1: > > conn = fnGetConnection(conn, filter, -1); returns this record: > > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; ToNodePin:0} > > The validation: if (forward ? conn->ToNode == KSFILTER_NODE : > > conn->FromNode == KSFILTER_NODE) > > is false, because conn->FromNode is 0. > > The validation: if (filter->nodes->Count > 0 && !forward && muxPosition > > >= 0) > > is true because muxPosition==0. > > The validation: if (IsEqualGUID(&nodes[conn->FromNode], &KSNODETYPE_MUX)) > > is true *again*, so we continue to > > ULONG nConn = GetNumberOfConnectionsTo(conn, filter); > > which gets the value *1, again*, and > > conn = fnGetConnection(conn, filter, muxPosition); > > which gets the value of this record: > > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; ToNodePin:1} *again > > * > > The validation: if (muxInputPinId != 0) > > is false *again *because muxInputPinId is indeed 0. > > The validation: if (muxNodeId != 0) > > is true *again *because muxNodeId is indeed still a valid pointer > > So the line: *muxNodeId = conn->ToNode; > > is executed *again*, which sets *muxNodeId = *0* - which is the value > > it already had. > > while(1) LOOP 2 -> 8: > > Same as LOOP 1. > > > > *CONCLUSION:* > > It seems my topology/architecture doesn't behave quite like the library > > expects - either it or the library doesn't follow the specifications 100%. > > There is no crash and nothing is obviously wrong, there's just an infinite > > loop, because of the way data is interpreted. > > > > *QUICK AND DIRTY FIX:* > > Replace the *while(1)* with something else. > > And then return an error value of some sort - not sure what that should > > be, as the PinNew(..) code below the calling point (line 1768) doesn't > > check for errors.We'd therefore have to alter the PinNew(..) code too. > > > > *A MORE ELABORATE QUICK FIX:* > > Keep track of the data from last iteration, and if the exact same data > > appears twice it is clear that we're hung. > > Again we'd have to think up a return value to signal error condition and a > > way to catch it in PinNew(..) > > > > *THE BEST AND MOST TIME CONSUMING FIX:* > > Find out *why* GetConnectedPin(..) gets stuck and fix it for real... > > > > > > RECOMMENDATION: > > I personally have lived and been contend with the latency of standard > > windows audio, and if I really wanted to do something more serious with > > Audacity I'd probably buy new hardware. > > So I recommend either of the quick fixes, and then an explanation aimed at > > those who really wanted the low-latency audio - a first-failure dialog for > > instance? > > > > // Lasse |
From: Gale A. <ga...@au...> - 2013-09-19 22:01:19
|
| From Gale Andrews <ga...@au...> | Thu, 19 Sep 2013 22:46:12 +0100 | Subject: [Audacity-devel] Debugging never-ending portaudio init > > | From Lasse Steen Bohnstedt <las...@gm...> > | Thu, 19 Sep 2013 14:02:38 +0200 > | Subject: [Audacity-devel] Debugging never-ending portaudio init > > I just tested "QUICK AND DIRTY FIX" with *success*. > > Simply replacing the line: > > while(1) > > with this: > > long lTimeout = 1024; while(--lTimeout) > > means I run Audacity with no problems. I can even use the WDM-KS setting > > and both recording and playback works fine. > > Audacity loads in 4 seconds, which is quite normal on my system and is > > great considering I run Debug mode from within Visual Studio. > > > > I also tested what I called the "MORE ELABORATE QUICK FIX" - that one > > failed with an assertion, obviously because I did it wrong somehow.... ;) > > > > // Lasse > > Hi, > > I've been getting some feedback now from Leland's build that > writes a debugging log file (and I think has some fixes to work > around loops). > > That build has solved the XP hang in the two cases tested so > far. WDM-KS loads, though one report suggests MME and > WASAPI are missing - I'm awaiting clarification). I've attached > the log files from these two cases. Forget WASAPI, sorry - that won't be there on XP. But it should list MME as well as Windows WDM-KS and Windows DirectSound. Gale > That build does nothing for BSOD's either on XP or Windows 7, > and there is usually no log file produced in BSOD cases. > > I'll write to Leland off-list about that. > > > Gale |
From: Gale A. <ga...@au...> - 2013-09-20 17:31:58
Attachments:
xp_hang_fixed_mme_and_no_mme.zip
|
| From Gale Andrews <ga...@au...> | Thu, 19 Sep 2013 23:01:00 +0100 | Subject: [Audacity-devel] Debugging never-ending portaudio init > > | From Gale Andrews <ga...@au...> > | Thu, 19 Sep 2013 22:46:12 +0100 > | Subject: [Audacity-devel] Debugging never-ending portaudio init > > > > | From Lasse Steen Bohnstedt <las...@gm...> > > | Thu, 19 Sep 2013 14:02:38 +0200 > > | Subject: [Audacity-devel] Debugging never-ending portaudio init > > > I just tested "QUICK AND DIRTY FIX" with *success*. > > > Simply replacing the line: > > > while(1) > > > with this: > > > long lTimeout = 1024; while(--lTimeout) > > > means I run Audacity with no problems. I can even use the WDM-KS setting > > > and both recording and playback works fine. > > > Audacity loads in 4 seconds, which is quite normal on my system and is > > > great considering I run Debug mode from within Visual Studio. > > > > > > I also tested what I called the "MORE ELABORATE QUICK FIX" - that one > > > failed with an assertion, obviously because I did it wrong somehow.... ;) > > > > > > // Lasse > > > > Hi, > > > > I've been getting some feedback now from Leland's build that > > writes a debugging log file (and I think has some fixes to work > > around loops). > > > > That build has solved the XP hang in the two cases tested so > > far. WDM-KS loads, though one report suggests MME and > > WASAPI are missing - I'm awaiting clarification). I've attached > > the log files from these two cases. > > Forget WASAPI, sorry - that won't be there on XP. > > But it should list MME as well as Windows WDM-KS and > Windows DirectSound. > > > > Gale I've attached another zip of pa logs from two XP users who had hangs. "User1" in the zip was the one I mentioned who only had WDS and WDM-KS listed (MME was missing). He ran Leland's diagnostic build again with apparently no device changes, and this time MME showed up. The zip contains the logs from both runs. The zip also includes a pa log from "user2" who had MME missing on one attempt. I'll try out Lasse's patch that just does: - while (1) + long lTimeout = 1024; + while(--lTimeout) on some users. Is this only useful for people who had hangs (mainly XP users), or also for BSOD's? Martyn wrote: > Your solution just 'fails' quickly each time, and would not 'fail' if > things on the system change, such as cards or drivers, which is > probably better. There could be a discussion over that. I tend to agree that failing WDM-KS each time is better, because user does not have to find and update a preference if the system changes. I agree with Lasse that user should be warned of the failure. Perhaps showing that warning should be a preference, rather than the preference being to enable/disable WDM-KS. But that only applies if BSOD's can be fixed, I feel. A BSOD should disable WDM-KS in a Preference. Gale |
From: Leland <le...@au...> - 2013-09-20 17:39:28
|
On 9/20/2013 12:31 PM, Gale Andrews wrote: > I'll try out Lasse's patch that just does: > > - while (1) > + long lTimeout = 1024; > + while(--lTimeout) > > on some users. Is this only useful for people who had hangs (mainly > XP users), or also for BSOD's? Actually, that's basically the same thing as the patch you've had them try. Both just limit the maximum number of iterations the loop is allowed to perform. So, know real need to have them retest...at least not until we come up with some sort of detection scheme for the loop. Leland |
From: Martyn S. <mar...@gm...> - 2013-09-19 23:46:17
Attachments:
pa_win_wdmks.c.patch
|
Thanks Lasse, great work! You have located the exact place of the hang, it appears. And great work from Leland, Gale and some other users/contributors as well on getting this tracked down! I don't know if you reviewed Leland's patch that he sent you (which is huge) but you are both clearly at the same culprit, although you have the major advantage of having a 'failing' system and he doesn't. He is clearly 'fishing', as that's the best he could do, and cunning 'fishing' tactics! Nice one Leland! Maybe analysis of Leland's log files, gathered by Gale from other users will reveal further problems, I hope not! Leland's patch has a cunning (possibly over-complicated) test for the hang with CheckWDMKS, which I see isn't actually in use (it just returns, part of an experiment I guess). But an effort not to 'fail' at every launch by remembering the 'fail'. Your solution just 'fails' quickly each time, and would not 'fail' if things on the system change, such as cards or drivers, which is probably better. There could be a discussion over that. So we are nearly at a fix for this problem! I have been trying to replicate the problem with 'dusted off' and borrowed hardware, but failed to make a 'fail' machine (Sound Blaster Audigy 2 tried tonight with various drivers). What a great example of teamwork in FOSS! QA, devel, user/new devel, users, all contributing to find a solution to a problem! I attach a patch for your recommended solution, so that QA (Gale) can try it out / get others to try it. It is very little. TTFN Martyn On 19/09/2013 13:58, Lasse Steen Bohnstedt wrote: > Actually I'll vote as such: > > +1 to quick and dirty fix - it is very quick to implement, it seems to > work, and we don't have to know what's going on. Maybe the value > should be higher than 1024. I have timed the Release version of 2.0.4 > now, and it loads half a second faster than 2.0.3 for me (no idea > why), so 1024 loops are not slowing things down in any way that can be > measured on my (slow) system. > > -1 to "a more elaborate quick fix" - it wouldn't be enough to just > quit if current and the latest values are equal; what if loops 1, 3, > 5, etc.. were equal and 2, 4, 6, etc were equal? Or what if the > pattern of re-occurrence was even more complex? It *could* be done, > but it would be - well - elaborate. > > // Lasse > > "There is a crack in everything, that's how the light gets in." - L. Cohen > > > On Thu, Sep 19, 2013 at 2:02 PM, Lasse Steen Bohnstedt > <las...@gm... <mailto:las...@gm...>> > wrote: > > I just tested "QUICK AND DIRTY FIX" with *success*. > Simply replacing the line: > while(1) > with this: > long lTimeout = 1024; while(--lTimeout) > means I run Audacity with no problems. I can even use the WDM-KS > setting and both recording and playback works fine. > Audacity loads in 4 seconds, which is quite normal on my system > and is great considering I run Debug mode from within Visual Studio. > > I also tested what I called the "MORE ELABORATE QUICK FIX" - that > one failed with an assertion, obviously because I did it wrong > somehow.... ;) > > // Lasse > > "There is a crack in everything, that's how the light gets in." - > L. Cohen > > > On Thu, Sep 19, 2013 at 1:27 PM, Lasse Steen Bohnstedt > <las...@gm... > <mailto:las...@gm...>> wrote: > > In short I see that the portaudio initialization never > completes on my system, because it keeps looping around in a > *while(1)* inside the function *GetConnectedPin(..)*. > It keeps churning away on what to me seems like perfectly > valid data. > I haven't yet had the time to fully understand the > functionality of the code (or the architecture), so I'm > presenting my findings here - maybe somebody else will know > what's going on precisely, so we can shortcut the learning > curve... > > This will be a bit long. Skip half way down to "THE ONE THAT > GOES BERSERK" if you feel confident this is obvious to you ;-) > > _THE ONE THAT'S OK:_ > First time inside GetConnectedPin(..) is OK. > Called from pa_win_wdmks.c/PinNew(..) line 1563, > right after this: PA_DEBUG(("PinNew: Finding topology > pin...\n")); > while(1) LOOP 0: > FindStartConnectionFrom(..) gets > this KSTOPOLOGY_CONNECTION record: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; > ToNodePin: 0} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : > conn->FromNode == KSFILTER_NODE) > is false because FromNode isn't KSFILTER_NODE. > The validation in the line: > if (filter->nodes->Count > 0 && !forward && > muxPosition >= 0) > is false, because muxPosition==-1 > while(1) LOOP 1: > fnGetConnection(..) gets this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; > ToNodePin: 1} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : > conn->FromNode == KSFILTER_NODE) > is true, so: > return forward ? conn->ToNodePin : conn->FromNodePin; > is executed. Yay! So the return value is 1. > > It turns out this is a physical connection we found, so the > PinNew(...) function continues at line 1627. It turns out the > connection has this name: > symbLinkName "\??\HDAUDIO#FUNC_01&VEN_10EC&DEV_0885&SUBSYS_106B3600&REV_1001#4&26c46e2&0&0001#{6994ad04-93ef-11d0-a3cc-00a0c9223196}\DigitalInputTopo"wchar_t > [260] > I have no idea whether this is meaningful or not. At least it > doesn't appear to be cut off, as it is way shorter than 260 chars. > This line is run: PA_DEBUG(("PinNew: Creating topology filter > '%S'\n", symbLinkName)); > This line is run: PA_DEBUG(("PinNew: Opening topology > filter...")); > This line is run: if (pin->dataFlow == KSPIN_DATAFLOW_IN) - > but it passed for the *else* clause, as > pin->dataFlow==KSPIN_DATAFLOW_OUT > This line is run: PA_DEBUG(("PinNew: Checking for input > endpoint pin id (%d)...\n", i)); > And now we descend into the GetConnectedPin(..) that never > completes. > > _THE ONE THAT GOES BERSERK_: > GetConnectedPin(..) is now called from > pa_win_wdmks.c/PinNew(..) line 1760. > while(1) LOOP 0: > FindStartConnectionFrom(..) gets > this KSTOPOLOGY_CONNECTION record *again*: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; > ToNodePin: 0} > The validation in the line: > if (forward ? conn->ToNode == KSFILTER_NODE : > conn->FromNode == KSFILTER_NODE) > is false because FromNode isn't KSFILTER_NODE. *Again.* > The validation in the line: > if (filter->nodes->Count > 0 && !forward && > muxPosition >= 0) > is true this time, because muxPosition==0 > The validation line: > if (IsEqualGUID(&nodes[conn->FromNode], > &KSNODETYPE_MUX)) > is true, so we continue to > ULONG nConn = GetNumberOfConnectionsTo(conn, filter); > which gets the value *1*, and > conn = fnGetConnection(conn, filter, muxPosition); > which gets the value of this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; > ToNodePin:1} > The validation: if (muxInputPinId != 0) > is false because muxInputPinId is indeed 0. > The validation: if (muxNodeId != 0) > is true because muxNodeId is indeed a valid pointer (note: > Why don't they enter it as "if (muxNodeId != NULL)" ???? Would > make it more obvious!) > So the line: *muxNodeId = conn->ToNode; > is executed, which sets *muxNodeId = *0* instead of the > value -1 (aka KSFILTER_NODE) it had before. > (note: This value is entered from PinNew(..) with the var > name of "muxNodeId*Test*", so it's probably fine it's thrown > away.) > while(1) LOOP 1: > conn = fnGetConnection(conn, filter, -1); returns this record: > {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; > ToNodePin:0} > The validation: if (forward ? conn->ToNode == KSFILTER_NODE > : conn->FromNode == KSFILTER_NODE) > is false, because conn->FromNode is 0. > The validation: if (filter->nodes->Count > 0 && !forward && > muxPosition >= 0) > is true because muxPosition==0. > The validation: if (IsEqualGUID(&nodes[conn->FromNode], > &KSNODETYPE_MUX)) > is true *again*, so we continue to > ULONG nConn = GetNumberOfConnectionsTo(conn, filter); > which gets the value *1, again*, and > conn = fnGetConnection(conn, filter, muxPosition); > which gets the value of this record: > {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; > ToNodePin:1} *again* > The validation: if (muxInputPinId != 0) > is false *again *because muxInputPinId is indeed 0. > The validation: if (muxNodeId != 0) > is true *again *because muxNodeId is indeed still a valid > pointer > So the line: *muxNodeId = conn->ToNode; > is executed *again*, which sets *muxNodeId = *0* - which is > the value it already had. > while(1) LOOP 2 -> ∞: > Same as LOOP 1. > > _CONCLUSION:_ > It seems my topology/architecture doesn't behave quite like > the library expects - either it or the library doesn't follow > the specifications 100%. > There is no crash and nothing is obviously wrong, there's just > an infinite loop, because of the way data is interpreted. > > _QUICK AND DIRTY FIX:_ > Replace the *while(1)* with something else. > And then return an error value of some sort - not sure what > that should be, as the PinNew(..) code below the calling point > (line 1768) doesn't check for errors.We'd therefore have to > alter the PinNew(..) code too. > > _A MORE ELABORATE QUICK FIX:_ > Keep track of the data from last iteration, and if the exact > same data appears twice it is clear that we're hung. > Again we'd have to think up a return value to signal error > condition and a way to catch it in PinNew(..) > > _THE BEST AND MOST TIME CONSUMING FIX:_ > Find out *why* GetConnectedPin(..) gets stuck and fix it for > real... > > > RECOMMENDATION: > I personally have lived and been contend with the latency of > standard windows audio, and if I really wanted to do something > more serious with Audacity I'd probably buy new hardware. > So I recommend either of the quick fixes, and then an > explanation aimed at those who really wanted the low-latency > audio - a first-failure dialog for instance? > > // Lasse > > "There is a crack in everything, that's how the light gets > in." - L. Cohen > > > > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > > > > _______________________________________________ > audacity-devel mailing list > aud...@li... > https://lists.sourceforge.net/lists/listinfo/audacity-devel > |
From: Vaughan J. <va...@au...> - 2013-09-20 01:27:35
|
+1 to all those comments, and especially the efforts on this! - V On 9/19/2013 4:46 PM, Martyn Shaw wrote: > Thanks Lasse, great work! You have located the exact place of the hang, > it appears. > > And great work from Leland, Gale and some other users/contributors as > well on getting this tracked down! > > I don't know if you reviewed Leland's patch that he sent you (which is > huge) but you are both clearly at the same culprit, although you have > the major advantage of having a 'failing' system and he doesn't. He is > clearly 'fishing', as that's the best he could do, and cunning 'fishing' > tactics! Nice one Leland! > > Maybe analysis of Leland's log files, gathered by Gale from other users > will reveal further problems, I hope not! > > Leland's patch has a cunning (possibly over-complicated) test for the > hang with CheckWDMKS, which I see isn't actually in use (it just > returns, part of an experiment I guess). But an effort not to 'fail' at > every launch by remembering the 'fail'. Your solution just 'fails' > quickly each time, and would not 'fail' if things on the system change, > such as cards or drivers, which is probably better. There could be a > discussion over that. > > So we are nearly at a fix for this problem! > > I have been trying to replicate the problem with 'dusted off' and > borrowed hardware, but failed to make a 'fail' machine (Sound Blaster > Audigy 2 tried tonight with various drivers). > > What a great example of teamwork in FOSS! QA, devel, user/new devel, > users, all contributing to find a solution to a problem! > > I attach a patch for your recommended solution, so that QA (Gale) can > try it out / get others to try it. It is very little. > > TTFN > Martyn > > On 19/09/2013 13:58, Lasse Steen Bohnstedt wrote: >> Actually I'll vote as such: >> >> +1 to quick and dirty fix - it is very quick to implement, it seems to >> work, and we don't have to know what's going on. Maybe the value >> should be higher than 1024. I have timed the Release version of 2.0.4 >> now, and it loads half a second faster than 2.0.3 for me (no idea >> why), so 1024 loops are not slowing things down in any way that can be >> measured on my (slow) system. >> >> -1 to "a more elaborate quick fix" - it wouldn't be enough to just >> quit if current and the latest values are equal; what if loops 1, 3, >> 5, etc.. were equal and 2, 4, 6, etc were equal? Or what if the >> pattern of re-occurrence was even more complex? It *could* be done, >> but it would be - well - elaborate. >> >> // Lasse >> >> "There is a crack in everything, that's how the light gets in." - L. >> Cohen >> >> >> On Thu, Sep 19, 2013 at 2:02 PM, Lasse Steen Bohnstedt >> <las...@gm... <mailto:las...@gm...>> >> wrote: >> >> I just tested "QUICK AND DIRTY FIX" with *success*. >> Simply replacing the line: >> while(1) >> with this: >> long lTimeout = 1024; while(--lTimeout) >> means I run Audacity with no problems. I can even use the WDM-KS >> setting and both recording and playback works fine. >> Audacity loads in 4 seconds, which is quite normal on my system >> and is great considering I run Debug mode from within Visual Studio. >> >> I also tested what I called the "MORE ELABORATE QUICK FIX" - that >> one failed with an assertion, obviously because I did it wrong >> somehow.... ;) >> >> // Lasse >> >> "There is a crack in everything, that's how the light gets in." - >> L. Cohen >> >> >> On Thu, Sep 19, 2013 at 1:27 PM, Lasse Steen Bohnstedt >> <las...@gm... >> <mailto:las...@gm...>> wrote: >> >> In short I see that the portaudio initialization never >> completes on my system, because it keeps looping around in a >> *while(1)* inside the function *GetConnectedPin(..)*. >> It keeps churning away on what to me seems like perfectly >> valid data. >> I haven't yet had the time to fully understand the >> functionality of the code (or the architecture), so I'm >> presenting my findings here - maybe somebody else will know >> what's going on precisely, so we can shortcut the learning >> curve... >> >> This will be a bit long. Skip half way down to "THE ONE THAT >> GOES BERSERK" if you feel confident this is obvious to you ;-) >> >> _THE ONE THAT'S OK:_ >> First time inside GetConnectedPin(..) is OK. >> Called from pa_win_wdmks.c/PinNew(..) line 1563, >> right after this: PA_DEBUG(("PinNew: Finding topology >> pin...\n")); >> while(1) LOOP 0: >> FindStartConnectionFrom(..) gets >> this KSTOPOLOGY_CONNECTION record: >> {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; >> ToNodePin: 0} >> The validation in the line: >> if (forward ? conn->ToNode == KSFILTER_NODE : >> conn->FromNode == KSFILTER_NODE) >> is false because FromNode isn't KSFILTER_NODE. >> The validation in the line: >> if (filter->nodes->Count > 0 && !forward && >> muxPosition >= 0) >> is false, because muxPosition==-1 >> while(1) LOOP 1: >> fnGetConnection(..) gets this record: >> {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; >> ToNodePin: 1} >> The validation in the line: >> if (forward ? conn->ToNode == KSFILTER_NODE : >> conn->FromNode == KSFILTER_NODE) >> is true, so: >> return forward ? conn->ToNodePin : conn->FromNodePin; >> is executed. Yay! So the return value is 1. >> >> It turns out this is a physical connection we found, so the >> PinNew(...) function continues at line 1627. It turns out the >> connection has this name: >> symbLinkName >> "\??\HDAUDIO#FUNC_01&VEN_10EC&DEV_0885&SUBSYS_106B3600&REV_1001#4&26c46e2&0&0001#{6994ad04-93ef-11d0-a3cc-00a0c9223196}\DigitalInputTopo"wchar_t >> >> [260] >> I have no idea whether this is meaningful or not. At least it >> doesn't appear to be cut off, as it is way shorter than 260 >> chars. >> This line is run: PA_DEBUG(("PinNew: Creating topology filter >> '%S'\n", symbLinkName)); >> This line is run: PA_DEBUG(("PinNew: Opening topology >> filter...")); >> This line is run: if (pin->dataFlow == KSPIN_DATAFLOW_IN) - >> but it passed for the *else* clause, as >> pin->dataFlow==KSPIN_DATAFLOW_OUT >> This line is run: PA_DEBUG(("PinNew: Checking for input >> endpoint pin id (%d)...\n", i)); >> And now we descend into the GetConnectedPin(..) that never >> completes. >> >> _THE ONE THAT GOES BERSERK_: >> GetConnectedPin(..) is now called from >> pa_win_wdmks.c/PinNew(..) line 1760. >> while(1) LOOP 0: >> FindStartConnectionFrom(..) gets >> this KSTOPOLOGY_CONNECTION record *again*: >> {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; >> ToNodePin: 0} >> The validation in the line: >> if (forward ? conn->ToNode == KSFILTER_NODE : >> conn->FromNode == KSFILTER_NODE) >> is false because FromNode isn't KSFILTER_NODE. *Again.* >> The validation in the line: >> if (filter->nodes->Count > 0 && !forward && >> muxPosition >= 0) >> is true this time, because muxPosition==0 >> The validation line: >> if (IsEqualGUID(&nodes[conn->FromNode], >> &KSNODETYPE_MUX)) >> is true, so we continue to >> ULONG nConn = GetNumberOfConnectionsTo(conn, filter); >> which gets the value *1*, and >> conn = fnGetConnection(conn, filter, muxPosition); >> which gets the value of this record: >> {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; >> ToNodePin:1} >> The validation: if (muxInputPinId != 0) >> is false because muxInputPinId is indeed 0. >> The validation: if (muxNodeId != 0) >> is true because muxNodeId is indeed a valid pointer (note: >> Why don't they enter it as "if (muxNodeId != NULL)" ???? Would >> make it more obvious!) >> So the line: *muxNodeId = conn->ToNode; >> is executed, which sets *muxNodeId = *0* instead of the >> value -1 (aka KSFILTER_NODE) it had before. >> (note: This value is entered from PinNew(..) with the var >> name of "muxNodeId*Test*", so it's probably fine it's thrown >> away.) >> while(1) LOOP 1: >> conn = fnGetConnection(conn, filter, -1); returns this record: >> {FromNode:0; FromNodePin:0; ToNode:KSFILTER_NODE; >> ToNodePin:0} >> The validation: if (forward ? conn->ToNode == KSFILTER_NODE >> : conn->FromNode == KSFILTER_NODE) >> is false, because conn->FromNode is 0. >> The validation: if (filter->nodes->Count > 0 && !forward && >> muxPosition >= 0) >> is true because muxPosition==0. >> The validation: if (IsEqualGUID(&nodes[conn->FromNode], >> &KSNODETYPE_MUX)) >> is true *again*, so we continue to >> ULONG nConn = GetNumberOfConnectionsTo(conn, filter); >> which gets the value *1, again*, and >> conn = fnGetConnection(conn, filter, muxPosition); >> which gets the value of this record: >> {FromNode:KSFILTER_NODE; FromNodePin:1; ToNode:0; >> ToNodePin:1} *again* >> The validation: if (muxInputPinId != 0) >> is false *again *because muxInputPinId is indeed 0. >> The validation: if (muxNodeId != 0) >> is true *again *because muxNodeId is indeed still a valid >> pointer >> So the line: *muxNodeId = conn->ToNode; >> is executed *again*, which sets *muxNodeId = *0* - which is >> the value it already had. >> while(1) LOOP 2 -> ∞: >> Same as LOOP 1. >> >> _CONCLUSION:_ >> It seems my topology/architecture doesn't behave quite like >> the library expects - either it or the library doesn't follow >> the specifications 100%. >> There is no crash and nothing is obviously wrong, there's just >> an infinite loop, because of the way data is interpreted. >> >> _QUICK AND DIRTY FIX:_ >> Replace the *while(1)* with something else. >> And then return an error value of some sort - not sure what >> that should be, as the PinNew(..) code below the calling point >> (line 1768) doesn't check for errors.We'd therefore have to >> alter the PinNew(..) code too. >> >> _A MORE ELABORATE QUICK FIX:_ >> Keep track of the data from last iteration, and if the exact >> same data appears twice it is clear that we're hung. >> Again we'd have to think up a return value to signal error >> condition and a way to catch it in PinNew(..) >> >> _THE BEST AND MOST TIME CONSUMING FIX:_ >> Find out *why* GetConnectedPin(..) gets stuck and fix it for >> real... >> >> >> RECOMMENDATION: >> I personally have lived and been contend with the latency of >> standard windows audio, and if I really wanted to do something >> more serious with Audacity I'd probably buy new hardware. >> So I recommend either of the quick fixes, and then an >> explanation aimed at those who really wanted the low-latency >> audio - a first-failure dialog for instance? >> >> // Lasse >> >> "There is a crack in everything, that's how the light gets >> in." - L. Cohen >> >> >> >> >> >> ------------------------------------------------------------------------------ >> >> LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! >> 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, >> SharePoint >> 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack >> includes >> Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. >> http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk >> >> >> >> >> _______________________________________________ >> audacity-devel mailing list >> aud...@li... >> https://lists.sourceforge.net/lists/listinfo/audacity-devel >> > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > > > > _______________________________________________ > audacity-devel mailing list > aud...@li... > https://lists.sourceforge.net/lists/listinfo/audacity-devel > |
From: Leland <le...@au...> - 2013-09-20 06:22:02
|
On 9/19/2013 4:46 PM, Gale Andrews wrote: > That build does nothing for BSOD's either on XP or Windows 7, and > there is usually no log file produced in BSOD cases. I'll write to > Leland off-list about that. Bummer! I was really hoping the file would survive the BSOD. I may be able to find a way to flush the write cache, but... Leland |
From: Lasse S. B. <las...@gm...> - 2013-09-20 09:17:32
|
Thanks Leland! I implemented your fix and it works well :) (although there were two typos, which I corrected here: https://docs.google.com/file/d/0B-9LFBxZUuOQWkhVcTRFWE5Zc2s/edit?usp=sharing) I had gotten it into my mind that it *wouldn't* be enough to only test for re-occurrences of the *conn* variable, so my (broken) attempt (the one I called "A MORE ELABORATE QUICK FIX") was far too complex it seems. The logs from portaudio can be viewed here: - Short one: "palog---PA_ENABLE_DEBUG_OUTPUT.txt" https://docs.google.com/file/d/0B-9LFBxZUuOQdGNrY0ZmVmRvTms/edit?usp=sharing - Long one: "palog---PA_ENABLE_DEBUG_OUTPUT+PA_LOG_API_CALLS.txt" https://docs.google.com/file/d/0B-9LFBxZUuOQQlhmUi1nNVNxMVk/edit?usp=sharing There are 4 loops detected and escaped from on my system. Sweet :D // Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen On Fri, Sep 20, 2013 at 8:22 AM, Leland <le...@au...> wrote: > On 9/19/2013 4:46 PM, Gale Andrews wrote: > > That build does nothing for BSOD's either on XP or Windows 7, and > > there is usually no log file produced in BSOD cases. I'll write to > > Leland off-list about that. > Bummer! I was really hoping the file would survive the BSOD. I may be > able to find a way to flush the write cache, but... > > Leland > > > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, > SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack > includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > _______________________________________________ > audacity-devel mailing list > aud...@li... > https://lists.sourceforge.net/lists/listinfo/audacity-devel > |
From: Leland <le...@au...> - 2013-09-20 14:57:24
|
On 9/20/2013 4:16 AM, Lasse Steen Bohnstedt wrote: > I had gotten it into my mind that it *wouldn't* be enough to only test > for re-occurrences of the *conn* variable, so my (broken) attempt (the > one I called "A MORE ELABORATE QUICK FIX") was far too complex it seems. Actually, looking over your logs, I think you may have been going down the right path. How many loops are detected if you put your limiter back in and disable my detector? I'm thinking you're going to see only 1. That means my detector is a bit too simplistic. Thanks, Leland |
From: Leland <le...@au...> - 2013-09-20 14:13:27
|
On 9/20/2013 4:16 AM, Lasse Steen Bohnstedt wrote: > Thanks Leland! > > I implemented your fix and it works well :) (although there were two > typos, which I corrected here: > https://docs.google.com/file/d/0B-9LFBxZUuOQWkhVcTRFWE5Zc2s/edit?usp=sharing > ) Awesome! Thanks for testing it for me. I've brought all of this up on the portaudio mailing list, but I haven't heard anything back as yet. Again, if they can't recreate, then it'll be slow going. But, thanks to you and the other adventurous users, we may be able to resolve at least the loop issue. > I had gotten it into my mind that it *wouldn't* be enough to only test > for re-occurrences of the *conn* variable Tried testing for pin and node as well? I thought about it, but I was too lazy to give it a go. :-) Figured I'd just try this route first. Thanks again, Leland |
From: Lasse S. B. <las...@gm...> - 2013-09-20 14:45:25
|
Please mind the typos! They meant that only the _seenndx_ variable was being used, _seencnt_ was only initialized to 0, never incremented (I'm just saying this so you don't present incorrect code to the portaudio team...) Tnx //Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen On Fri, Sep 20, 2013 at 4:13 PM, Leland <le...@au...> wrote: > On 9/20/2013 4:16 AM, Lasse Steen Bohnstedt wrote: > > Thanks Leland! > > > > I implemented your fix and it works well :) (although there were two > > typos, which I corrected here: > > > https://docs.google.com/file/d/0B-9LFBxZUuOQWkhVcTRFWE5Zc2s/edit?usp=sharing > > ) > Awesome! Thanks for testing it for me. I've brought all of this up on > the portaudio mailing list, but I haven't heard anything back as yet. > Again, if they can't recreate, then it'll be slow going. > > But, thanks to you and the other adventurous users, we may be able to > resolve at least the loop issue. > > > I had gotten it into my mind that it *wouldn't* be enough to only test > > for re-occurrences of the *conn* variable > Tried testing for pin and node as well? I thought about it, but I was > too lazy to give it a go. :-) Figured I'd just try this route first. > > Thanks again, > > Leland > > > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, > SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack > includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > _______________________________________________ > audacity-devel mailing list > aud...@li... > https://lists.sourceforge.net/lists/listinfo/audacity-devel > |
From: Leland <le...@au...> - 2013-09-20 15:56:01
|
On 9/20/2013 9:44 AM, Lasse Steen Bohnstedt wrote: > Please mind the typos! They meant that only the _seenndx_ variable was > being used, _seencnt_ was only initialized to 0, never incremented > (I'm just saying this so you don't present incorrect code to the > portaudio team...) Yep, saw your changes (thanks for the extra eyeballs ;-)), but I don't believe this is quite ready to send over to the portaudio folks. Thanks, Leland |
From: Alan H. <gi...@as...> - 2013-09-20 20:17:59
|
There is a cautionary tale here... (cc to Portaudio list) On Friday 20 September 2013 00:46, Martyn Shaw wrote: <snip> > I attach a patch <snip.> It is very little. > > TTFN > Martyn > Index: lib-src/portaudio-v19/src/hostapi/wdmks/pa_win_wdmks.c > =================================================================== > --- lib-src/portaudio-v19/src/hostapi/wdmks/pa_win_wdmks.c (revision > 12571) > +++ lib-src/portaudio-v19/src/hostapi/wdmks/pa_win_wdmks.c (working copy) > @@ -1059,7 +1059,8 @@ > { > const KSTOPOLOGY_CONNECTION *conn = NULL; > TFnGetConnection fnGetConnection = forward ? GetConnectionTo : > > GetConnectionFrom ; > - while (1) > + long lTimeout = 1024; > + while(--lTimeout) > { > if (conn == NULL) > { IMHO 'while (1)' IS a bug in itself, nearly always; defensive coding requires being able to guarantee a timely exit in all circumstances. The consequences are less serious on a desktop than on an embedded device, but still quite undesirable. A very quick search in the Portaudio src find 5 occurrences; one in OSS and 4 in WDMKS. Perhaps there is a slightly wider vulnerability here. Regards Alan |
From: Lasse S. B. <las...@gm...> - 2013-09-23 07:54:34
|
There's a problem with Leland's loop-detection in GetConnectedPin(..) - it prevents Audacity from finding all devices on my system - and those found have "generic" names (fx "input" and "output" rather than "microphone" and "speaker"). It would seem it *isn't* enough to check only for re-occurring values of the conn value - apparently it leads to false positives. Also I suppose the loop-detection has a memory leak as it doesn't clean up the array it creates (very minor problem). See these screen-dump images from the *loop-detection* version: GetConnectedPin---Loop-detection---inputs.jpg<https://docs.google.com/file/d/0B-9LFBxZUuOQRVhRTkZfVjB2Uk0/edit?usp=drive_web> 3 inputs found (I'm translating the names to English here): (a) "Input (Realtek HD Digital input)" (b) "Input (Realtek HD Audio Input)" (c) "Input (USB audio device)" GetConnectedPin---Loop-detection---outputs.jpg<https://docs.google.com/file/d/0B-9LFBxZUuOQSmdFS290Z2MxaEE/edit?usp=drive_web> 2 outputs found (again translated for the Danish impaired lol!): (x) "Output 1 (Realtek HD Audio output)" (y) "Output 2 (Realtek HD Audio output)" And compare with these from my *timeout-with-the-fancy-magic-number-of-1024*version: GetConnectedPin---Timeout---outputs.jpg<https://docs.google.com/file/d/0B-9LFBxZUuOQN0ZZUVBZYlNBZmM/edit?usp=drive_web> 5 inputs found (names translated to English): (1) "Input (Realtek HD Digital input)" // same device as (a) above (2) "Stereomix (Realtek HD Audio Input)" // same device as (b) above, but with better name (3) "Volume control for microphone (Realtek HD Audio Input)" // not found above (4) "Volume control for line-in (Realtek HD Audio Input)" // not found above (5) "Microphone (USB audio device)" // same as (c) above, but with better name GetConnectedPin---Timeout---inputs.jpg<https://docs.google.com/file/d/0B-9LFBxZUuOQQW81Y2lJNi1xUk0/edit?usp=drive_web> 2 outputs found: (I) "Speakers 1 (Realtek HD Audio output)" // same device as (x) above, but with better name (II) "Speakers 2 (Realtek HD Audio output)" // same device as (y) above, but with better name Anyway I'm very sorry for not noticing this so very obvious problem before! I was way too busy last week, and I didn't had time to do anything in the weekend either. Aaand when I tried to compile this morning Visual Studio kept on handing me linker errors - even after I did a full clean of the entire solution + a force update of Intellisense!!!!! Only solution was a svn revert and applying the changes again. %€&%"#"!!! So should I try to refine the loop detection? It would be quite straightforward but still some coding required because it would mean testing values of several other variables besides the _conn_ variable. On the other hand the *timeout-with-the-magic-number* version is a no-brainer - and it might be better to keep it simple? What say you? // Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen |
From: Leland <le...@au...> - 2013-09-23 08:58:57
|
On 9/23/2013 2:53 AM, Lasse Steen Bohnstedt wrote: > There's a problem with Leland's loop-detection in GetConnectedPin(..) > - it prevents Audacity from finding all devices on my system - and > those found have "generic" names (fx "input" and "output" rather than > "microphone" and "speaker"). So, my suspicions mentioned here: http://sourceforge.net/mailarchive/message.php?msg_id=31427504 were correct. > Also I suppose the loop-detection has a memory leak as it doesn't > clean up the array it creates (very minor problem). Yep, never said it was complete...just asked for assistance in testing. > So should I try to refine the loop detection? It would be quite > straightforward but still some coding required because it would mean > testing values of several other variables besides the _conn_ variable. > On the other hand the /timeout-with-the-magic-number/ version is a > no-brainer - and it might be better to keep it simple? > What say you? Absolutely continue on if you have the time. You're about our best bet in getting this resolved properly. Sure, the artificial limiter is okay (a "similar" limiter is already doing in the WDMKS code), but it would be nice to understand and resolve that actual problem. Leland |
From: Lasse S. B. <las...@gm...> - 2013-09-23 16:14:13
|
I'm attaching a diff with my code for loop detection. I've also kept the * magic-number-1024-timeout*, but I guess people aren't so happy about that ;-) pa_win_wdmks.c---with-new-loop-detection.diff<https://docs.google.com/file/d/0B-9LFBxZUuOQZkhVQTh5QzlWMlE/edit?usp=drive_web> Anyway, the 1024 timeout doesn't trigger now, as can be seen from this log: palog---with-new-loop-detection.txt<https://docs.google.com/file/d/0B-9LFBxZUuOQTzdBNTdYZUV5cFk/edit?usp=drive_web> Interestingly enough it only escapes from _one_ single loop, but it also fails in another way, that I've called "Erroneous connection list - part 2". I've tried my very best to keep it ANSI C - oh how I would have loved to be able to do it OO! Have a look at it, please. // Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen On Mon, Sep 23, 2013 at 10:58 AM, Leland <le...@au...> wrote: > On 9/23/2013 2:53 AM, Lasse Steen Bohnstedt wrote: > > There's a problem with Leland's loop-detection in GetConnectedPin(..) - it > prevents Audacity from finding all devices on my system - and those found > have "generic" names (fx "input" and "output" rather than "microphone" and > "speaker"). > > So, my suspicions mentioned here: > > http://sourceforge.net/mailarchive/message.php?msg_id=31427504 > > were correct. > > Also I suppose the loop-detection has a memory leak as it doesn't clean > up the array it creates (very minor problem). > > Yep, never said it was complete...just asked for assistance in testing. > > So should I try to refine the loop detection? It would be quite > straightforward but still some coding required because it would mean > testing values of several other variables besides the _conn_ variable. > On the other hand the *timeout-with-the-magic-number* version is a > no-brainer - and it might be better to keep it simple? > What say you? > > Absolutely continue on if you have the time. You're about our best bet in > getting this resolved properly. Sure, the artificial limiter is okay (a > "similar" limiter is already doing in the WDMKS code), but it would be nice > to understand and resolve that actual problem. > > Leland > > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, > SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack > includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > _______________________________________________ > audacity-devel mailing list > aud...@li... > https://lists.sourceforge.net/lists/listinfo/audacity-devel > > |
From: Leland <le...@au...> - 2013-09-25 17:46:38
|
Gale, I know you have a LOT of free time :-), but would you be able to apply this to a "test" build and ask a couple of the others that are have the looping issue give it a try? If it does work for them, then a copy of "Help -> Audio Device info" would be a good thing to have if Audacity successfully. Thanks, Leland On 9/23/2013 11:13 AM, Lasse Steen Bohnstedt wrote: > I'm attaching a diff with my code for loop detection. I've also kept > the /magic-number-1024-timeout/, but I guess people aren't so happy > about that ;-) > pa_win_wdmks.c---with-new-loop-detection.diff > <https://docs.google.com/file/d/0B-9LFBxZUuOQZkhVQTh5QzlWMlE/edit?usp=drive_web> > > Anyway, the 1024 timeout doesn't trigger now, as can be seen from this > log: > palog---with-new-loop-detection.txt > <https://docs.google.com/file/d/0B-9LFBxZUuOQTzdBNTdYZUV5cFk/edit?usp=drive_web> > Interestingly enough it only escapes from _one_ single loop, but it > also fails in another way, that I've called "Erroneous connection list > - part 2". > > > I've tried my very best to keep it ANSI C - oh how I would have loved > to be able to do it OO! > Have a look at it, please. > > > // Lasse > > "There is a crack in everything, that's how the light gets in." - L. Cohen > > > On Mon, Sep 23, 2013 at 10:58 AM, Leland <le...@au... > <mailto:le...@au...>> wrote: > > On 9/23/2013 2:53 AM, Lasse Steen Bohnstedt wrote: >> There's a problem with Leland's loop-detection in >> GetConnectedPin(..) - it prevents Audacity from finding all >> devices on my system - and those found have "generic" names (fx >> "input" and "output" rather than "microphone" and "speaker"). > So, my suspicions mentioned here: > > http://sourceforge.net/mailarchive/message.php?msg_id=31427504 > > were correct. > >> Also I suppose the loop-detection has a memory leak as it doesn't >> clean up the array it creates (very minor problem). > Yep, never said it was complete...just asked for assistance in > testing. >> So should I try to refine the loop detection? It would be quite >> straightforward but still some coding required because it would >> mean testing values of several other variables besides the _conn_ >> variable. >> On the other hand the /timeout-with-the-magic-number/ version is >> a no-brainer - and it might be better to keep it simple? >> What say you? > Absolutely continue on if you have the time. You're about our > best bet in getting this resolved properly. Sure, the artificial > limiter is okay (a "similar" limiter is already doing in the WDMKS > code), but it would be nice to understand and resolve that actual > problem. > > Leland > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, > SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power > Pack includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > _______________________________________________ > audacity-devel mailing list > aud...@li... > <mailto:aud...@li...> > https://lists.sourceforge.net/lists/listinfo/audacity-devel > > > > > ------------------------------------------------------------------------------ > LIMITED TIME SALE - Full Year of Microsoft Training For Just $49.99! > 1,500+ hours of tutorials including VisualStudio 2012, Windows 8, SharePoint > 2013, SQL 2012, MVC 4, more. BEST VALUE: New Multi-Library Power Pack includes > Mobile, Cloud, Java, and UX Design. Lowest price ever! Ends 9/20/13. > http://pubads.g.doubleclick.net/gampad/clk?id=58041151&iu=/4140/ostg.clktrk > > > _______________________________________________ > audacity-devel mailing list > aud...@li... > https://lists.sourceforge.net/lists/listinfo/audacity-devel |
From: Gale A. <ga...@au...> - 2013-09-27 06:09:21
|
| From Leland <le...@au...> | Wed, 25 Sep 2013 12:46:33 -0500 | Subject: [Audacity-devel] Debugging never-ending portaudio init > Gale, > > I know you have a LOT of free time :-),but would you be able to > apply this to a "test" build and ask a couple of the others that are > have the looping issue give it a try? If it does work for them, then a > copy of "Help -> Audio Device info" would be a good thing to have if > Audacity successfully. OK I "assume" I patched it correctly using GNU patch - the SVN diff then was the same as Lasse's diff. But there is no debug log file, applying that patch on its own. Do we want a log file like Leland's patches had? If so, did you want me to apply Leland's patch, but using Lasse's pa_win_wdmks.c ? I too think there are problems with Leland's patch, based on the user comeback. In half the cases, MME is said to be missing (at least on some launches), even though the hang was fixed. I haven't seen any reported problems with missing inputs and outputs after running Leland's patch, but WDM-KS is reported to have that problem already on some machines in current HEAD. Were you missing inputs and outputs under all hosts, Lasse, or just WDM-KS? Gale > On 9/23/2013 11:13 AM, Lasse Steen Bohnstedt wrote: > > I'm attaching a diff with my code for loop detection. I've also kept > the /magic-number-1024-timeout/, but I guess people aren't so happy > about that ;-) > > pa_win_wdmks.c---with-new-loop-detection.diff > <https://docs.google.com/file/d/0B-9LFBxZUuOQZkhVQTh5QzlWMlE/edit?usp=drive_web> > > > > Anyway, the 1024 timeout doesn't trigger now, as can be seen from this > log: > > palog---with-new-loop-detection.txt > <https://docs.google.com/file/d/0B-9LFBxZUuOQTzdBNTdYZUV5cFk/edit?usp=drive_web> > > Interestingly enough it only escapes from _one_ single loop, but it > also fails in another way, that I've called "Erroneous connection list > - part 2". > > > > > > I've tried my very best to keep it ANSI C - oh how I would have loved > to be able to do it OO! > > Have a look at it, please. > > > > > > // Lasse > > > > "There is a crack in everything, that's how the light gets in." - L. Cohen > > > > > > On Mon, Sep 23, 2013 at 10:58 AM, Leland <le...@au... > <mailto:le...@au...>> wrote: > > > > On 9/23/2013 2:53 AM, Lasse Steen Bohnstedt wrote: > >> There's a problem with Leland's loop-detection in > >> GetConnectedPin(..) - it prevents Audacity from finding all > >> devices on my system - and those found have "generic" names (fx > >> "input" and "output" rather than "microphone" and "speaker"). > > So, my suspicions mentioned here: > > > > http://sourceforge.net/mailarchive/message.php?msg_id=31427504 > > > > were correct. > > > >> Also I suppose the loop-detection has a memory leak as it doesn't > >> clean up the array it creates (very minor problem). > > Yep, never said it was complete...just asked for assistance in > > testing. > >> So should I try to refine the loop detection? It would be quite > >> straightforward but still some coding required because it would > >> mean testing values of several other variables besides the _conn_ > >> variable. > >> On the other hand the /timeout-with-the-magic-number/ version is > >> a no-brainer - and it might be better to keep it simple? > >> What say you? > > Absolutely continue on if you have the time. You're about our > > best bet in getting this resolved properly. Sure, the artificial > > limiter is okay (a "similar" limiter is already doing in the WDMKS > > code), but it would be nice to understand and resolve that actual > > problem. > > > > Leland |
From: Lasse S. B. <las...@gm...> - 2013-09-27 06:50:33
|
@Gale: When I tried Leland's fix I lacked 2 WDMKS inputs and the remaining 2 inputs were incorrectly named - as were the WDMKS outputs. MME worked fine for me. I think it's very system/driver dependent. Also I forgot the debug log file code - sorry if you wasted a lot of time there. Btw I dusted off and booted my very stale OSX 10.5 Leopard partition on this machine (yes it's a macbook, and I'm running WinXP on it!) to see if there would be any problems with audio drivers there for 2.0.4 - after all it's the same hardware. But it worked fine. I also tried to compile Audacity from source, but got stuck in update-everything-you-have-before-you-can-do-anything-useful limbo. But this is not the thread for that. // Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen On Fri, Sep 27, 2013 at 8:08 AM, Gale Andrews <ga...@au...> wrote: > > | From Leland <le...@au...> > | Wed, 25 Sep 2013 12:46:33 -0500 > | Subject: [Audacity-devel] Debugging never-ending portaudio init > > Gale, > > > > I know you have a LOT of free time :-),but would you be able to > > apply this to a "test" build and ask a couple of the others that are > > have the looping issue give it a try? If it does work for them, then a > > copy of "Help -> Audio Device info" would be a good thing to have if > > Audacity successfully. > > OK I "assume" I patched it correctly using GNU patch - the SVN > diff then was the same as Lasse's diff. > > But there is no debug log file, applying that patch on its own. Do > we want a log file like Leland's patches had? If so, did you want me > to apply Leland's patch, but using Lasse's pa_win_wdmks.c ? > > I too think there are problems with Leland's patch, based on > the user comeback. In half the cases, MME is said to be missing > (at least on some launches), even though the hang was fixed. > > I haven't seen any reported problems with missing inputs and > outputs after running Leland's patch, but WDM-KS is reported to > have that problem already on some machines in current HEAD. > > Were you missing inputs and outputs under all hosts, Lasse, or > just WDM-KS? > > > > Gale > > > > On 9/23/2013 11:13 AM, Lasse Steen Bohnstedt wrote: > > > I'm attaching a diff with my code for loop detection. I've also kept > > the /magic-number-1024-timeout/, but I guess people aren't so happy > about > that ;-) > > > pa_win_wdmks.c---with-new-loop-detection.diff > < > https://docs.google.com/file/d/0B-9LFBxZUuOQZkhVQTh5QzlWMlE/edit?usp=drive_web > > > > > > > > Anyway, the 1024 timeout doesn't trigger now, as can be seen from this > > log: > > > palog---with-new-loop-detection.txt > < > https://docs.google.com/file/d/0B-9LFBxZUuOQTzdBNTdYZUV5cFk/edit?usp=drive_web > > > > > Interestingly enough it only escapes from _one_ single loop, but it > > also fails in another way, that I've called "Erroneous connection list > - > part 2". > > > > > > > > > I've tried my very best to keep it ANSI C - oh how I would have loved > > to be able to do it OO! > > > Have a look at it, please. > > > > > > > > > // Lasse > > > > > > "There is a crack in everything, that's how the light gets in." - L. > Cohen > > > > > > > > > On Mon, Sep 23, 2013 at 10:58 AM, Leland <le...@au... > > <mailto:le...@au...>> wrote: > > > > > > On 9/23/2013 2:53 AM, Lasse Steen Bohnstedt wrote: > > >> There's a problem with Leland's loop-detection in > > >> GetConnectedPin(..) - it prevents Audacity from finding all > > >> devices on my system - and those found have "generic" names (fx > > >> "input" and "output" rather than "microphone" and "speaker"). > > > So, my suspicions mentioned here: > > > > > > http://sourceforge.net/mailarchive/message.php?msg_id=31427504 > > > > > > were correct. > > > > > >> Also I suppose the loop-detection has a memory leak as it doesn't > > >> clean up the array it creates (very minor problem). > > > Yep, never said it was complete...just asked for assistance in > > > testing. > > >> So should I try to refine the loop detection? It would be quite > > >> straightforward but still some coding required because it would > > >> mean testing values of several other variables besides the _conn_ > > >> variable. > > >> On the other hand the /timeout-with-the-magic-number/ version is > > >> a no-brainer - and it might be better to keep it simple? > > >> What say you? > > > Absolutely continue on if you have the time. You're about our > > > best bet in getting this resolved properly. Sure, the artificial > > > limiter is okay (a "similar" limiter is already doing in the WDMKS > > > code), but it would be nice to understand and resolve that actual > > > problem. > > > > > > Leland > > > > ------------------------------------------------------------------------------ > October Webinars: Code for Performance > Free Intel webinars can help you accelerate application performance. > Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most > from > the latest Intel processors and coprocessors. See abstracts and register > > http://pubads.g.doubleclick.net/gampad/clk?id=60133471&iu=/4140/ostg.clktrk > _______________________________________________ > audacity-devel mailing list > aud...@li... > https://lists.sourceforge.net/lists/listinfo/audacity-devel > |
From: Lasse S. B. <las...@gm...> - 2013-09-27 07:41:33
|
(Also I apologize there are tabs inserted - vs did it and I didn't notice) |
From: Lasse S. B. <las...@gm...> - 2013-10-02 12:32:05
|
Bump... NB: I personally have no problem with this issue not being resolved until later - or indeed not at all - even though I am one of those unfortunate who are affected by it. I'll just stick to my own compiled version, and if I hadn't had that I'd just have stayed with 2.0.3 as long as my WinXP partition lives. It's just that it is my perception that this is being forgotten without there having been made a decision to do so? // Lasse "There is a crack in everything, that's how the light gets in." - L. Cohen |