Firebase database, C++: crash in transaction handler on Linux

150 views
Skip to first unread message

Andy Tai

unread,
Oct 21, 2019, 4:30:47 PM10/21/19
to fireba...@googlegroups.com
Hi, I wonder if anyone runs into the problem of crash in transaction handler using C++ on Linux (Fedora and Ubuntu):

Using Firebase C++ SDK, version 6.6.1., on GNU/Linux (Fedora or Ubuntu), with gcc 9.1, the crash can be triggered if I replace the transaction code in the quick start app with this block of code in common_main.cc:

    // The transaction will set the player's item and class, and increment
    // their score by 100 points.
    int score_delta = 100;
    transaction_future =
        ref.Child("TransactionResult")
            .RunTransaction(
                [score_delta](firebase::database::MutableData* data) {
                  LogMessage("  Transaction function executing.");
                  LogMessage("data key %s", data->key());
                  data->Child("player_item").set_value("Fire sword");
                  data->Child("player_class").set_value("Warrior");
                  // Increment the current score by 100.
                  int64_t score = data->Child("player_score")
                                      .value()
                                      .AsInt64()
                                      .int64_value();
                  data->Child("player_score")
                      .set_value(score +
                                 (score_delta));

                  std::map<std::string, std::string> map = {
                    {"1", "v1"},
                    {"2", "v2"},
                    {"3", "v3"},
                    {std::to_string(score_delta), "v" + std::to_string(score_delta)}
                  };
                  data->set_value(map);
                  LogMessage("  Transaction function complete.");
                  return firebase::database::kTransactionResultSuccess;
                },
                true);
    WaitForCompletion(transaction_future, "RunTransaction");

the crash is in data->key() that caused a seg fault.   

I filed an issue but am not sure if the Firebase people watching over the bug reports pay attention to the C++ SDK issues.  

This same code works fine on Mac OSX with xcode.

Thanks for any information on this.

--
Andy Tai, at...@atai.org, Skype: licheng.tai, Line: andy_tai, WeChat: andytai1010
Year 2019 民國108年
自動的精神力是信仰與覺悟
自動的行為力是勞動與技能

Patrick Martin

unread,
Oct 22, 2019, 1:31:00 PM10/22/19
to Firebase Google Group
For clarity on this bug:
Does it occur with the original function as written or did you only test with your above changes?
Also, can you give us more information on the segfault? Was `data` NULL, do other accessors break on `data` (ex: data->Child), or does it seem like an issue with `key()` itself? If it's an issue with `key()`, can you fix it with key_string().c_str() or by changing the printf to a std::cout << data->key_string()?

Thanks,
--Patrick

Andy Tai

unread,
Oct 22, 2019, 7:04:43 PM10/22/19
to fireba...@googlegroups.com
Also note the original sample did not crash; but the problem with the original sample is that the transaction handler was a simple function, not a lambda.

If I convert the transaction handler to a form using the lambda (std::function<void(firebase::database::MutableData* data)>), such as applying the attached diff, the crash happens:
TEST: Run transaction.
** Message: Remote error from secret service: org.freedesktop.Secret.Error.IsLocked: Cannot create an item in a locked collection
WARNING: Secret store failed, please make sure libsecret is installed.
  Transaction function executing.

Thread 5 "desktop_testapp" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffeeffd700 (LWP 28828)]
0x00007ffff735fcdf in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) where
#0  0x00007ffff735fcdf in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00000000008b228a in std::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, char const*) ()
#2  0x00000000009167d1 in firebase::Path::GetChild(std::string const&) const ()
#3  0x000000000080ab13 in firebase::database::internal::MutableDataInternal::Child(char const*) ()
#4  0x00000000007ef398 in firebase::database::MutableData::Child(char const*) ()
#5  0x00000000007d85bd in <lambda(firebase::database::MutableData*)>::operator()(firebase::database::MutableData *) const (__closure=0xf22790, data=0x7fffe0023c10)
    at /share/software/firebase_sdk/quickstart-cpp.git/database/testapp/src/common_main.cc:452
#6  0x00000000007e0e4b in std::_Function_handler<firebase::database::TransactionResult(firebase::database::MutableData*), common_main(int, char const**)::<lambda(firebase::database::MutableData*)> >::_M_invoke(const std::_Any_data &, firebase::database::MutableData *&&) (__functor=...,
    __args#0=@0x7fffeeffc9f0: 0x7fffe0023c10) at /usr/include/c++/9/bits/std_function.h:285
#7  0x00000000007ee905 in std::function<firebase::database::TransactionResult (firebase::database::MutableData*)>::operator()(firebase::database::MutableData*) const ()
#8  0x00000000007ee291 in firebase::database::CallStdFunction(firebase::database::MutableData*, void*) ()
#9  0x000000000083cad9 in firebase::database::internal::Repo::StartTransaction(firebase::Path const&, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>) ()
#10 0x00000000008045e6 in firebase::database::internal::DatabaseReferenceInternal::RunTransaction(firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool)::{lambda(firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>)#1}::operator()(firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>) const ()
#11 0x000000000080464b in firebase::database::internal::DatabaseReferenceInternal::RunTransaction(firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool)::{lambda(firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>)#1}::_FUN(firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>) ()
#12 0x0000000000809d68 in void firebase::callback::CallbackVariadic<firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot> >::RunInternal<0, 1, 2, 3, 4, 5, 6, 7>(firebase::callback::IntegerSequence<0, 1, 2, 3, 4, 5, 6, 7>) ()
#13 0x00000000008095e7 in firebase::callback::CallbackVariadic<firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot> >::Run() ()
#14 0x000000000091c6cb in firebase::scheduler::Scheduler::TriggerCallback(firebase::SharedPtr<firebase::scheduler::Scheduler::RequestData> const&) ()
#15 0x000000000091c4c7 in firebase::scheduler::Scheduler::WorkerThreadRoutine(void*) ()
#16 0x0000000000920de4 in void std::_Bind_simple<void (*(void*))(void*)>::_M_invoke<0ul>(std::_Index_tuple<0ul>) ()
#17 0x0000000000920c49 in std::_Bind_simple<void (*(void*))(void*)>::operator()() ()
#18 0x0000000000920b7a in std::thread::_Impl<std::_Bind_simple<void (*(void*))(void*)> >::_M_run() ()
#19 0x00007ffff73474ee in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6

#20 0x00007ffff7bc16ba in start_thread (arg=0x7fffeeffd700) at pthread_create.c:333
#21 0x00007ffff6a9341d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109



On Tue, Oct 22, 2019 at 1:06 PM Andy Tai <at...@atai.org> wrote:
Hi, using data->key_string() resulting in the same crash

gdb backtrace:

Starting program: /home/lctai/basic_data/share/software/firebase_sdk/quickstart-cpp.git/database/testapp/desktop_testapp
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Initialized Firebase App.
Initialize Firebase Auth and Firebase Database.
Attempt to initialize Firebase Auth.
[New Thread 0x7ffff4fe4700 (LWP 27246)]
[New Thread 0x7fffeffff700 (LWP 27247)]
[New Thread 0x7fffef7fe700 (LWP 27248)]
Attempt to initialize Firebase Database.
[New Thread 0x7fffeeffd700 (LWP 27249)]
Successfully initialized Firebase Auth and Firebase Database.
WARNING: Persistence is not currently supported.
[New Thread 0x7fffee7fc700 (LWP 27250)]
[New Thread 0x7fffedffb700 (LWP 27251)]
[New Thread 0x7fffed7fa700 (LWP 27252)]
[New Thread 0x7fffecff9700 (LWP 27253)]
[New Thread 0x7fffd7fff700 (LWP 27254)]
** Message: Remote error from secret service: org.freedesktop.Secret.Error.IsLocked: Cannot create an item in a locked collection
WARNING: Secret store failed, please make sure libsecret is installed.
Auth: Signed in anonymously.
URL: https://magic-spaces.firebaseio.com/test_app_data/-Lrp36R-5qqzixa8xAAA
TEST: Run transaction.
  Transaction function executing.

Thread 5 "desktop_testapp" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffeeffd700 (LWP 27249)]
0x00007ffff735e04d in std::string::find_last_of(char const*, unsigned long, unsigned long) const () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
(gdb) where
#0  0x00007ffff735e04d in std::string::find_last_of(char const*, unsigned long, unsigned long) const () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x0000000000904c14 in firebase::Path::GetBaseName() const ()
#2  0x00000000007f76c5 in firebase::database::internal::MutableDataInternal::GetKeyString() const ()
#3  0x00000000007db2b0 in firebase::database::MutableData::key_string() const ()
#4  0x00000000007d248b in <lambda(firebase::database::MutableData*)>::operator()(firebase::database::MutableData *) const (__closure=0xf0dfb0, data=0x7fffe000ba70)
    at /share/software/firebase_sdk/quickstart-cpp.git/database/testapp/src/common_main.cc:249
#5  0x00000000007d3a53 in std::_Function_handler<firebase::database::TransactionResult(firebase::database::MutableData*), common_main(int, char const**)::<lambda(firebase::database::MutableData*)> >::_M_invoke(const std::_Any_data &, firebase::database::MutableData *&&) (__functor=...,
    __args#0=@0x7fffeeffc9f0: 0x7fffe000ba70) at /usr/include/c++/9/bits/std_function.h:285
#6  0x00000000007dad57 in std::function<firebase::database::TransactionResult (firebase::database::MutableData*)>::operator()(firebase::database::MutableData*) const ()
#7  0x00000000007da633 in firebase::database::CallStdFunction(firebase::database::MutableData*, void*) ()
#8  0x000000000082a09d in firebase::database::internal::Repo::StartTransaction(firebase::Path const&, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>) ()
#9  0x00000000007f047a in firebase::database::internal::DatabaseReferenceInternal::RunTransaction(firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool)::{lambda(firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>)#1}::operator()(firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>) const ()
#10 0x00000000007f04df in firebase::database::internal::DatabaseReferenceInternal::RunTransaction(firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool)::{lambda(firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>)#1}::_FUN(firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot>) ()
#11 0x00000000007f6586 in void firebase::callback::CallbackVariadic<firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot> >::RunInternal<0, 1, 2, 3, 4, 5, 6, 7>(firebase::callback::IntegerSequence<0, 1, 2, 3, 4, 5, 6, 7>) ()
#12 0x00000000007f5e05 in firebase::callback::CallbackVariadic<firebase::database::internal::Repo*, firebase::Path, firebase::database::TransactionResult (*)(firebase::database::MutableData*, void*), void*, void (*)(void*), bool, firebase::ReferenceCountedFutureImpl*, firebase::SafeFutureHandle<firebase::database::DataSnapshot> >::Run() ()
#13 0x000000000090a95d in firebase::scheduler::Scheduler::TriggerCallback(firebase::SharedPtr<firebase::scheduler::Scheduler::RequestData> const&) ()
#14 0x000000000090a759 in firebase::scheduler::Scheduler::WorkerThreadRoutine(void*) ()
#15 0x000000000090f076 in void std::_Bind_simple<void (*(void*))(void*)>::_M_invoke<0ul>(std::_Index_tuple<0ul>) ()
#16 0x000000000090eedb in std::_Bind_simple<void (*(void*))(void*)>::operator()() ()
#17 0x000000000090ee0c in std::thread::_Impl<std::_Bind_simple<void (*(void*))(void*)> >::_M_run() ()
#18 0x00007ffff73474ee in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#19 0x00007ffff7bc16ba in start_thread (arg=0x7fffeeffd700) at pthread_create.c:333
#20 0x00007ffff6a9341d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

For your reference, I attached the complete common_main.cc I used as attachment.  Put it in place of the original src/common_main.cc and rebuild, using the quickstart app sample as the test bed

--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/753e2a2a-e37e-4a4d-980e-9d6d5b56f24c%40googlegroups.com.


--
Andy Tai, at...@atai.org, Skype: licheng.tai, Line: andy_tai, WeChat: andytai1010
Year 2019 民國108年
自動的精神力是信仰與覺悟
自動的行為力是勞動與技能
diff

Andy Tai

unread,
Oct 22, 2019, 7:04:44 PM10/22/19
to fireba...@googlegroups.com
--
You received this message because you are subscribed to the Google Groups "Firebase Google Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/753e2a2a-e37e-4a4d-980e-9d6d5b56f24c%40googlegroups.com.
common_main.cc

Alex Ames

unread,
Oct 22, 2019, 7:35:16 PM10/22/19
to Firebase Google Group
Hi Andy, 

I tried running your code verbatim and didn't see any crash. Looking at the code under the hood, it's really hard to figure out how this could be SIGSEGV-ing because the code is pretty simple and straighforward. 

Is it the key()/key_string() functions that are crashing, or do other functions crash as well? `data` is not a nullptr, right? (I can't think of how it could be null, but I'm just trying to rule out possible failures.) Is it possible that you got your firebase libraries mismatched or something when updating to 6.6.1? Maybe try starting from a totally clean project and seeing if this still happens.

Alex


To unsubscribe from this group and stop receiving emails from it, send an email to fireba...@googlegroups.com.

Andy Tai

unread,
Oct 22, 2019, 8:38:42 PM10/22/19
to fireba...@googlegroups.com
Alex, I am using the prebuilt binary from the release from the Firebase web site.  Yes, the code is pretty simple and straightforward.   

The crash is in the part referencing the key() or key_string() function.  As I was using the quick start app as the test bed, I built it following the documentation exactly.   

The only thing I can think of, is that,  was the Firebase release, the Linux x86-64 binaries, built with clang?   I was building on Linux with gcc 9.1.   Not sure can this cause problems?

To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/2e8636d5-75dd-4f99-b9d2-1003142f5404%40googlegroups.com.

Patrick Martin

unread,
Oct 23, 2019, 1:28:35 PM10/23/19
to Firebase Google Group
While I try to get an answer to that specific question, if you use CMake it's not incredibly difficult to add Firebase via add_subdirectory:
https://github.com/firebase/firebase-cpp-sdk#including-in-projects

Just make sure you make sure that you have the prerequisites:

If you're able to do that and it fixes your issue: let us know and we can figure out what to do about our binary builds. If it doesn't, at least it's easier to coordinate with full source on both ends.

--Patrick

Mark Chandler

unread,
Oct 30, 2019, 12:02:20 PM10/30/19
to Firebase Google Group
Hi Andy,

Looks like the issue is that the Linux release build uses clang and libc++ where as you are trying to use gcc and libstdc++ causing the std::string object to have different implementation and causing a runtime break. We are looking at adding a check into the linux build to pick this up in the future but I would suggest building from source on linux using CMake.

Mark

Andy Tai

unread,
Oct 30, 2019, 7:55:54 PM10/30/19
to fireba...@googlegroups.com
Thanks... This is surprising as c++ ABI is compatible...  Will try to rebuild.

To unsubscribe from this group and stop receiving emails from it, send an email to firebase-tal...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/firebase-talk/a832a5df-e703-4b18-bbd7-fa91ccdce5c5%40googlegroups.com.

Mark Chandler

unread,
Oct 30, 2019, 7:59:58 PM10/30/19
to Firebase Google Group
C++ ABI is not compatible (only C is). Can read up on how std::string changes per compiler and std lib: https://shaharmike.com/cpp/std-string/
Reply all
Reply to author
Forward
0 new messages