URL class SigSegv

This happens when i try to use the URL class and read the stream (either as XML or String). Don’t really know what i’m doing wrong…
The whole thing is a one-liner

return (URL (updateUrl).withParameter("revision", String(ctrlrRevision)).withParameter("osname", getOsIdea()).withParameter("osbits", getOsBitIdea()).readEntireXmlStream());

but it fails

Program received signal SIGSEGV, Segmentation fault.
0x0807c6a7 in juce::Atomic<int>::operator++ (this=0x829e4e3) at /home/atom/devel/juce/juce_amalgamated.h:2412
2412		return (Type) __sync_add_and_fetch (&value, 1);
(gdb) backtrace
#0  0x0807c6a7 in juce::Atomic<int>::operator++ (this=0x829e4e3) at /home/atom/devel/juce/juce_amalgamated.h:2412
#1  0x0831bce5 in juce::StringHolder::retain (text=...) at /home/atom/devel/juce/amalgamation/../src/text/juce_String.cpp:156
#2  0x082b8129 in String (this=0x8abc050, other=...) at /home/atom/devel/juce/amalgamation/../src/text/juce_String.cpp:243
#3  0x083236d3 in juce::Array<juce::String, juce::DummyCriticalSection>::add (this=0xbfffe384, newElement=...)
    at /home/atom/devel/juce/amalgamation/../src/core/../io/files/../../containers/juce_Array.h:337
#4  0x082bd9fc in juce::StringArray::add (this=0xbfffe384, newString=...) at /home/atom/devel/juce/amalgamation/../src/text/juce_StringArray.cpp:134
#5  0x082bef06 in juce::StringPairArray::set (this=0xbfffe370, key=..., value=...) at /home/atom/devel/juce/amalgamation/../src/text/juce_StringPairArray.cpp:97
#6  0x082b1b27 in juce::URL::withParameter (this=0xbfffe3f8, parameterName=..., parameterValue=...) at /home/atom/devel/juce/amalgamation/../src/io/network/juce_URL.cpp:344
#7  0x0816afec in CtrlrAbout::getUpdateData (updateUrl=...) at ../../Source/UIComponents/CtrlrAbout.cpp:247
#8  0x0816adc6 in CtrlrAbout::buttonClicked (this=0x8ac3488, buttonThatWasClicked=0x8ad9230) at ../../Source/UIComponents/CtrlrAbout.cpp:202
#9  0x08515de5 in void juce::ListenerList<juce::Button::Listener, juce::Array<juce::Button::Listener*, juce::DummyCriticalSection> >::callChecked<juce::Component::BailOutChecker, juce::Button*>(juce::Component::BailOutChecker const&, void (juce::Button::Listener::*)(juce::Button*), juce::TypeHelpers::ParameterType<juce::Button*>::type) ()
#10 0x08452ca3 in juce::Button::sendClickMessage (this=0x8ad9230, modifiers=...) at /home/atom/devel/juce/amalgamation/../src/gui/components/buttons/juce_Button.cpp:384
#11 0x08452a6c in juce::Button::internalClickCallback (this=0x8ad9230, modifiers=...) at /home/atom/devel/juce/amalgamation/../src/gui/components/buttons/juce_Button.cpp:325
#12 0x08452f8f in juce::Button::mouseUp (this=0x8ad9230, e=...) at /home/atom/devel/juce/amalgamation/../src/gui/components/buttons/juce_Button.cpp:440
#13 0x0844bf1d in juce::Component::internalMouseUp (this=0x8ad9230, source=..., relativePos=..., time=..., oldModifiers=...)

Ah…

It’s seg-faulting because it’s trying to do an atomic operation on some unaligned memory - notice that the Atomic object’s address is 0x829e4e3.

That must be because ‘new’ isn’t producing an aligned block, but I’m a little surprised by that! On other platforms it certainly seems to always be 4-byte aligned. How about trying this, in juce_String.cpp:

static const CharPointerType createUninitialisedBytes (const size_t numBytes) { StringHolder* const s = reinterpret_cast <StringHolder*> (new int [(sizeof (StringHolder) - sizeof (CharType) + sizeof (int) - 1 + numBytes) / sizeof (int)]);

…could be that because it was doing a ‘new char […’, gcc was assuming that it’d be ok to return a non-aligned block from some kind of specialised small-block pool or something. Hopefully asking it for an array of ints will make it realise that it should align the result.

didn’t help, i changed

static const CharPointerType createUninitialisedBytes (const size_t numBytes)
    {
        // StringHolder* const s = reinterpret_cast <StringHolder*> (new char [sizeof (StringHolder) - sizeof (CharType) + numBytes]);
        StringHolder* const s = reinterpret_cast <StringHolder*> (new int [(sizeof (StringHolder) - sizeof (CharType) + sizeof (int) - 1 + numBytes) / sizeof (int)]);
        s->refCount.value = 0;
        s->allocatedNumBytes = numBytes;
        return CharPointerType (s->text);
    }

and the backtrace is (you can see the line numbers moved +1 so the change is there:

Program received signal SIGSEGV, Segmentation fault.
0x0807c6a7 in juce::Atomic<int>::operator++ (this=0x829e4e3) at /home/atom/devel/juce/juce_amalgamated.h:2412
2412		return (Type) __sync_add_and_fetch (&value, 1);
(gdb) backtrace
#0  0x0807c6a7 in juce::Atomic<int>::operator++ (this=0x829e4e3) at /home/atom/devel/juce/juce_amalgamated.h:2412
#1  0x0831bceb in juce::StringHolder::retain (text=...) at /home/atom/devel/juce/amalgamation/../src/text/juce_String.cpp:157
#2  0x082b8129 in String (this=0x8ab2730, other=...) at /home/atom/devel/juce/amalgamation/../src/text/juce_String.cpp:244
#3  0x083236d9 in juce::Array<juce::String, juce::DummyCriticalSection>::add (this=0xbfffef64, newElement=...)
    at /home/atom/devel/juce/amalgamation/../src/core/../io/files/../../containers/juce_Array.h:337
#4  0x082bd9fc in juce::StringArray::add (this=0xbfffef64, newString=...) at /home/atom/devel/juce/amalgamation/../src/text/juce_StringArray.cpp:134
#5  0x082bef06 in juce::StringPairArray::set (this=0xbfffef50, key=..., value=...) at /home/atom/devel/juce/amalgamation/../src/text/juce_StringPairArray.cpp:97
#6  0x082b1b27 in juce::URL::withParameter (this=0xbfffefd8, parameterName=..., parameterValue=...) at /home/atom/devel/juce/amalgamation/../src/io/network/juce_URL.cpp:344
#7  0x0816afec in CtrlrAbout::getUpdateData (updateUrl=...) at ../../Source/UIComponents/CtrlrAbout.cpp:247
#8  0x0820b01e in CtrlrMenu::timerCallback (this=0x8a9f9b8) at ../../Source/UIComponents/CtrlrMenu.cpp:502
#9  0x083bebf6 in juce::InternalTimerThread::callTimers (this=0x8a7b2d0) at /home/atom/devel/juce/amalgamation/../src/events/juce_Timer.cpp:138
#10 0x083bed1b in juce::InternalTimerThread::handleMessage (this=0x8a7b2d0) at /home/atom/devel/juce/amalgamation/../src/events/juce_Timer.cpp:154
#11 0x0837313b in juce::MessageManager::deliverMessage (this=0x8a1db40, message=0x8a7b650) at /home/atom/devel/juce/amalgamation/../src/events/juce_MessageManager.cpp:117
#12 0x085b9440 in juce::InternalMessageQueue::dispatchNextInternalMessage (this=0x8a1dba0) at /home/atom/devel/juce/amalgamation/../src/native/linux/juce_linux_Messaging.cpp:231
#13 0x085b8ee5 in juce::InternalMessageQueue::dispatchNextEvent (this=0x8a1dba0) at /home/atom/devel/juce/amalgamation/../src/native/linux/juce_linux_Messaging.cpp:101
#14 0x085aee21 in juce::MessageManager::dispatchNextMessageOnSystemQueue (returnIfNoPendingMessages=false) at /home/atom/devel/juce/amalgamation/../src/native/linux/juce_linux_Messaging.cpp:456
#15 0x08373389 in juce::MessageManager::runDispatchLoopUntil (this=0x8a1db40, millisecondsToRunFor=-1) at /home/atom/devel/juce/amalgamation/../src/events/juce_MessageManager.cpp:149
#16 0x0837326e in juce::MessageManager::runDispatchLoop (this=0x8a1db40) at /home/atom/devel/juce/amalgamation/../src/events/juce_MessageManager.cpp:129
#17 0x0833824f in juce::JUCEApplication::main (commandLine=...) at /home/atom/devel/juce/amalgamation/../src/application/juce_Application.cpp:230
#18 0x08338428 in juce::JUCEApplication::main (argc=1, argv=0xbffff4b4) at /home/atom/devel/juce/amalgamation/../src/application/juce_Application.cpp:264
#19 0x0808bd74 in main (argc=1, argv=0xbffff4b4) at ../../Source/Application/StandaloneWrapper/CtrlrStandaloneApplication.cpp:38

i did a complete clean and re-built the whole thing. Weird thing is the Introjucer works with it’s update feature, i add some GET paramters to the URL and that might be different (the StringPairArray seems to be involved here so i’m guessing that’s where the parameters are kept)

Wow, so the allocator is returning un-aligned arrays of ints…?? That’s a pretty poor job that the compiler’s doing, as it could have a huge performance hit, because on some CPUs, accessing each int will burn extra cycles when they’re not aligned.

Ok… try it with malloc:

static const CharPointerType createUninitialisedBytes (const size_t numBytes) { StringHolder* const s = reinterpret_cast <StringHolder*> (juce_malloc (sizeof (StringHolder) - sizeof (CharType) + numBytes)); jassert ((((pointer_sized_int) s) & 3) == 0);

and you’ll also need:

static inline void release (StringHolder* const b) throw() { if (--(b->refCount) == -1 && b != &empty) juce_free (b);

I added an assertion in there too, so any unaligned addresses should get caught immediately…

still nothing, same error.

no, no, no… I think I may have been getting side-tracked here…

Are you sure you’re not just doing something silly? In your original code:

return (URL (updateUrl).withParameter("revision", String(ctrlrRevision)).withParameter("osname", getOsIdea()).withParameter("osbits", getOsBitIdea()).readEntireXmlStream());

…are you sure the return values of those “getOSBitIdea” things are valid? They’re not returning dangling references are they? Try it with some hard-coded strings in there.

well yes as usual you are correct, it was my fault (a missed a #ifdef and the compiler did not warn me about not returning anything from a function). I’m sorry for bugging you with that.

There is something about URL::launchInDefaultBrowser() when i call it the browser opens but my application catches a SIGSTOP and i can’t do anything about it, i tried
debugging it but this does not happen under GDB only when launched without the debugger:

atom@ubuntu-x32:~/devel/ctrlr/Builds/Linux$ ../../Bin/Debug/Ctrlr_Standalon
ERROR: X returned BadMatch (invalid parameter attributes) for operation X_ConfigureWindow
ERROR: X returned BadMatch (invalid parameter attributes) for operation X_ConfigureWindow
ERROR: X returned BadMatch (invalid parameter attributes) for operation X_ConfigureWindow
ERROR: X returned BadMatch (invalid parameter attributes) for operation X_ConfigureWindow
ERROR: X returned BadMatch (invalid parameter attributes) for operation X_ConfigureWindow
ERROR: X returned BadMatch (invalid parameter attributes) for operation X_ConfigureWindow
ERROR: X returned BadMatch (invalid parameter attributes) for operation X_ConfigureWindow

[1]+  Stopped                 ../../Bin/Debug/Ctrlr_Standalone

i tried doing “fg” but that does not seem to help, there is a “defunct” sh process that’s a child of my process and the app is not responding

1544  1548  1548  1548 pts/0     3340 Ss    1000   0:00  \_ bash
 1548  3340  3340  1548 pts/0     3340 tl+   1000   0:29  |   \_ ../../Bin/Debug/Ctrlr_Standalone
 3340  3342  3342  3342 ?           -1 Zs    1000   0:00  |       \_ [sh] <defunct>

sorry, not at all sure what’s going on there… Maybe it’s the browser process that’s blowing up?

hard to say, can’t really debug it so i don’t know where the signal is comming from, it’s not a big thing i’ll deal with it.

once again sorry for the stupid bug report, i’ll try to triple check everything now.