Open ciaran-moore opened 1 month ago
This looks like to me it cannot find libcassandra.so
the library that you have built from Datastax.
can you please do ld cassandra.so
, and paste the output here if you need any help.
cassandra.so -> PHP Driver and not libcassandra.so (the datastax driver)
Few suggestions to fix the issue
libcassandra.so
to LD_LIBRARY_PATH
/usr/lib
or some equivalent directoryApologies for the delay in responding. I have been caught out by some BAU work.
I trashed the previous box and done a fresh install of everything. Still on Deb12 with a PHP8.2 install. This time copying libcassandra.so
before building.
These are the steps performed after installing the system pre-requisites / recommended packages:
# Manually Install Libuv
git clone https://github.com/libuv/libuv.git --recursive && cd libuv
sh autogen.sh
./configure
make
sudo make install
# Manually Install libcassandra
git clone https://github.com/datastax/cpp-driver.git --recursive
mkdir cpp-driver/build && cd cpp-driver/build
cmake ..
make
sudo make install
# Copy libcassandra library to lib from x86_64 folder
sudo cp /usr/local/lib/x86_64-linux-gnu/libcassandra.so.2.17.1 /usr/local/lib/libcassandra.so.2.17.1; \
sudo ln -s /usr/local/lib/libcassandra.so.2.17.1 /usr/local/lib/libcassandra.so.2; \
sudo ln -s /usr/local/lib/libcassandra.so.2 /usr/local/lib/libcassandra.so
# Build php-driver
git clone https://github.com/he4rt/scylladb-php-driver.git --recursive;
cmake --preset ReleaseLibCassandra -DPHP_SCYLLADB_USE_LIBCASSANDRA=ON -DPHP_SCYLLADB_LIBUV_STATIC=ON && cd out/ReleaseLibCassandra && sudo ninja install
# Extension not showing after install. Found INI file hadn't been set.
echo "extension=cassandra.so" | sudo tee -a $(php-config --ini-dir)/cassandra.ini
php -m
shows cassandra extension correctly.
Switching users was still providing the PHP Startup Warning
PHP Warning: PHP Startup: Unable to load dynamic library 'cassandra.so' (tried: /usr/lib/php/20220829/cassandra.so (libcassandra.so.2: cannot open shared object file: No such file or directory), /usr/lib/php/20220829/cassandra.so.so (/usr/lib/php/20220829/cassandra.so.so: cannot open shared object file: No such file or directory)) in Unknown on line 0
However, expecting this was a linking issue. Doing sudo ldconfig
on additional users cleared this warning and showed the extension loaded correctly.
Unfortunately for me, fixing this issue has led to finding another. I am now receiving this error when attempting to test:
php: /home/ciaran/cpp-driver/src/ref_counted.hpp:43: void datastax::internal::RefCounted<T>::dec_ref() const [with T = datastax::internal::core::RetryPolicy]: Assertion `new_ref_count >= 1' failed.
Aborted
Not sure why it's defaulted to using the home folder for the header directory. The path which the error is reporting (/home/ciaran/cpp-driver/src/ref_counted.hpp) no longer exists after I installed libcassandra
Okay, it looks like an issue maybe with Debian 12?
The ref_counted.hpp
issue is present in the scylliadb-cpp-driver
and the datastax-cpp-driver
with the latest versions of the drivers. After adding some debugging to the ref_counted.hpp
file, both in the Datastax and ScylliaDB CPP-Driver I can see that the RetryPolicy ref_count decrements down to 0, and the address doesn't seem to be freed?
Decrement to 0 --> dec_ref called on type: N8datastax8internal4core11RetryPolicyE | ref_count before: 1, after: 0 | on thread: 140426676909760
dec_ref called on type: N8datastax8internal4core26SpeculativeExecutionPolicyE | ref_count before: 1, after: 0 | on thread: 140426676909760
dec_ref called on type: N8datastax8internal4core14AddressFactoryE | ref_count before: 1, after: 0 | on thread: 140426676909760
dec_ref called on type: N8datastax8internal4core27RequestProcessorInitializerE | ref_count before: 3, after: 2 | on thread: 140426676909760
dec_ref called on type: N8datastax8internal4core7ClusterE | ref_count before: 3, after: 2 | on thread: 140426676909760
dec_ref called on type: N8datastax8internal4core14AddressFactoryE | ref_count before: 3, after: 2 | on thread: 140426676909760
dec_ref called on type: N8datastax8internal4core26SpeculativeExecutionPolicyE | ref_count before: 4, after: 3 | on thread: 140426676909760
reference still being used --> dec_ref called on type: N8datastax8internal4core11RetryPolicyE | ref_count before: -1390838656, after: -1390838657 | on thread: 140426676909760
php: /home/ciaran/cpp-driver/src/ref_counted.hpp:55: void datastax::internal::RefCounted<T>::dec_ref() const [with T = datastax::internal::core::RetryPolicy]: Assertion `new_ref_count >= 1' failed.
Okay, so using php8.2/8.3 on Debian 12 this issue with ref_count happens in each version of the php-driver down to v1.3.8
.
I'm not sure what has happened, but it seems that there is a SharedRefPtr somewhere which either isn't freed, or there are objects still referencing it after it has been freed?
I used GDB to perform a backtrace on a Query to system.local
and got this:
Starting program: /usr/bin/php /home/ciaran/cassandra_test.php
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Querying Cassandra - system
[New Thread 0x7fffee94b6c0 (LWP 199786)]
[New Thread 0x7fffebbff6c0 (LWP 199787)]
[New Thread 0x7fffeb3fe6c0 (LWP 199788)]
[New Thread 0x7fffeabfd6c0 (LWP 199789)]
[New Thread 0x7fffea3fc6c0 (LWP 199790)]
[New Thread 0x7fffe9bfb6c0 (LWP 199792)]
php: /home/ciaran/cpp-driver/src/ref_counted.hpp:43: void datastax::internal::RefCounted<T>::dec_ref() const [with T = datastax::internal::core::RetryPolicy]: Assertion `new_ref_count >= 1' failed.
Thread 2 "php" received signal SIGABRT, Aborted.
[Switching to Thread 0x7fffee94b6c0 (LWP 199786)]
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt 1000
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1 0x00007ffff74a9e9f in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2 0x00007ffff745afb2 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x00007ffff7445472 in __GI_abort () at ./stdlib/abort.c:79
#4 0x00007ffff7445395 in __assert_fail_base (fmt=0x7ffff75b9a90 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x7fffef1befc4 "new_ref_count >= 1", file=file@entry=0x7fffef1bef98 "/home/ciaran/cpp-driver/src/ref_counted.hpp", line=line@entry=43,
function=function@entry=0x7fffef1bf048 "void datastax::internal::RefCounted<T>::dec_ref() const [with T = datastax::internal::core::RetryPolicy]") at ./assert/assert.c:92
#5 0x00007ffff7453eb2 in __GI___assert_fail (assertion=0x7fffef1befc4 "new_ref_count >= 1", file=0x7fffef1bef98 "/home/ciaran/cpp-driver/src/ref_counted.hpp", line=43, function=0x7fffef1bf048 "void datastax::internal::RefCounted<T>::dec_ref() const [with T = datastax::internal::core::RetryPolicy]") at ./assert/assert.c:101
#6 0x00007fffef00af8b in datastax::internal::RefCounted<datastax::internal::core::RetryPolicy>::dec_ref() const () from /usr/local/lib/libcassandra.so.2
#7 0x00007fffef00ad8b in datastax::internal::SharedRefPtr<datastax::internal::core::RetryPolicy>::~SharedRefPtr() () from /usr/local/lib/libcassandra.so.2
#8 0x00007fffef01216e in datastax::internal::core::ExecutionProfile::~ExecutionProfile() () from /usr/local/lib/libcassandra.so.2
#9 0x00007fffef117dd4 in datastax::internal::core::RequestProcessorSettings::~RequestProcessorSettings() () from /usr/local/lib/libcassandra.so.2
#10 0x00007fffef12b1f2 in datastax::internal::core::SessionInitializer::initialize(datastax::internal::SharedRefPtr<datastax::internal::core::Host> const&, datastax::internal::core::ProtocolVersion, datastax::internal::Map<datastax::internal::core::Address, datastax::internal::SharedRefPtr<datastax::internal::core::Host>, std::less<datastax::internal::core::Address> > const&, datastax::internal::SharedRefPtr<datastax::internal::core::TokenMap> const&, std::__cxx11::basic_string<char, std::char_traits<char>, datastax::internal::Allocator<char> > const&) () from /usr/local/lib/libcassandra.so.2
#11 0x00007fffef128f0d in datastax::internal::core::Session::on_connect(datastax::internal::SharedRefPtr<datastax::internal::core::Host> const&, datastax::internal::core::ProtocolVersion, datastax::internal::Map<datastax::internal::core::Address, datastax::internal::SharedRefPtr<datastax::internal::core::Host>, std::less<datastax::internal::core::Address> > const&, datastax::internal::SharedRefPtr<datastax::internal::core::TokenMap> const&, std::__cxx11::basic_string<char, std::char_traits<char>, datastax::internal::Allocator<char> > const&) () from /usr/local/lib/libcassandra.so.2
#12 0x00007fffef12f095 in datastax::internal::core::SessionBase::on_initialize(datastax::internal::core::ClusterConnector*) () from /usr/local/lib/libcassandra.so.2
#13 0x00007fffef1322b7 in datastax::internal::Callback<void, datastax::internal::core::ClusterConnector*>::MemberInvoker<void (datastax::internal::core::SessionBase::*)(datastax::internal::core::ClusterConnector*), datastax::internal::core::SessionBase>::invoke(datastax::internal::core::ClusterConnector* const&) const ()
from /usr/local/lib/libcassandra.so.2
#14 0x00007fffef052e7e in datastax::internal::Callback<void, datastax::internal::core::ClusterConnector*>::operator()(datastax::internal::core::ClusterConnector* const&) const () from /usr/local/lib/libcassandra.so.2
#15 0x00007fffef050cba in datastax::internal::core::ClusterConnector::finish() () from /usr/local/lib/libcassandra.so.2
#16 0x00007fffef050dae in datastax::internal::core::ClusterConnector::maybe_finish() () from /usr/local/lib/libcassandra.so.2
#17 0x00007fffef0510e4 in datastax::internal::core::ClusterConnector::on_connect(datastax::internal::core::ControlConnector*) () from /usr/local/lib/libcassandra.so.2
#18 0x00007fffef056561 in datastax::internal::Callback<void, datastax::internal::core::ControlConnector*>::MemberInvoker<void (datastax::internal::core::ClusterConnector::*)(datastax::internal::core::ControlConnector*), datastax::internal::core::ClusterConnector>::invoke(datastax::internal::core::ControlConnector* const&) const ()
from /usr/local/lib/libcassandra.so.2
#19 0x00007fffef09411c in datastax::internal::Callback<void, datastax::internal::core::ControlConnector*>::operator()(datastax::internal::core::ControlConnector* const&) const () from /usr/local/lib/libcassandra.so.2
#20 0x00007fffef091331 in datastax::internal::core::ControlConnector::finish() () from /usr/local/lib/libcassandra.so.2
#21 0x00007fffef091715 in datastax::internal::core::ControlConnector::on_connect(datastax::internal::core::Connector*) () from /usr/local/lib/libcassandra.so.2
#22 0x00007fffef09105d in datastax::internal::Callback<void, datastax::internal::core::Connector*>::MemberInvoker<void (datastax::internal::core::ControlConnector::*)(datastax::internal::core::Connector*), datastax::internal::core::ControlConnector>::invoke(datastax::internal::core::Connector* const&) const () from /usr/local/lib/libcassandra.so.2
#23 0x00007fffef08231c in datastax::internal::Callback<void, datastax::internal::core::Connector*>::operator()(datastax::internal::core::Connector* const&) const () from /usr/local/lib/libcassandra.so.2
#24 0x00007fffef0803d4 in datastax::internal::core::Connector::finish() () from /usr/local/lib/libcassandra.so.2
#25 0x00007fffef0810d1 in datastax::internal::core::Connector::on_close(datastax::internal::core::Connection*) () from /usr/local/lib/libcassandra.so.2
#26 0x00007fffef05f906 in datastax::internal::core::Connection::on_close() () from /usr/local/lib/libcassandra.so.2
#27 0x00007fffef05e59e in datastax::internal::core::ConnectionHandler::on_close() () from /usr/local/lib/libcassandra.so.2
#28 0x00007fffef133b18 in datastax::internal::core::Socket::handle_close() () from /usr/local/lib/libcassandra.so.2
#29 0x00007fffef1339df in datastax::internal::core::Socket::on_close(uv_handle_s*) () from /usr/local/lib/libcassandra.so.2
#30 0x00007fffef548645 in uv__finish_close (handle=0x7fffe400bec8) at /home/ciaran/scylladb-php-driver/out/ReleaseLibCassandra/_deps/libuv-src/src/unix/core.c:351
#31 uv__run_closing_handles (loop=0x555555bcd948) at /home/ciaran/scylladb-php-driver/out/ReleaseLibCassandra/_deps/libuv-src/src/unix/core.c:365
#32 uv_run (loop=0x555555bcd948, mode=UV_RUN_DEFAULT) at /home/ciaran/scylladb-php-driver/out/ReleaseLibCassandra/_deps/libuv-src/src/unix/core.c:463
#33 0x00007fffef0b981e in datastax::internal::core::EventLoop::handle_run() () from /usr/local/lib/libcassandra.so.2
#34 0x00007fffef0b97de in datastax::internal::core::EventLoop::internal_on_run(void*) () from /usr/local/lib/libcassandra.so.2
#35 0x00007ffff74a8144 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#36 0x00007ffff75287dc in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
This is consistent for v1.3.9 onwards, but v1.3.8 builds and works as expected?
Ok this is really strange, can you provide me full instructions how to reproduce everything in VPS server (looks like to me you are running VPS). If it's something that you dont want to share here, send me an email (dusan@dusanmalusev.dev)
Okay, so step by step detail from building the VPS are as follows.
Machine type | n2-custom-4-2048 CPU platform | N2 Minimum CPU platform | Intel Cascade Lake Architecture | x86/64
Single Region, 40GB SSD Image: debian-12-bookworm-v20241009 (Debian, Debian GNU/Linux, 12 (bookworm), amd64 built on 20241009) OS: Debian 12 Bookworm
Once disk is created and instance is loaded, copy install script and run with php-version as parameter:
sudo ./install.sh -p 8.3
This process is run manually with copy/paste rather than scripted to ensure that each command is running as it should.
Manually install the libuv library to ensure library is compiled with -fpic
# Manually Install Libuv
# pkg-config Name: libuv-static
# pkg-config Version: 1.49.1
git clone https://github.com/libuv/libuv.git --recursive && cd libuv
cmake -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=ON CMAKE_C_FLAGS="-fPIC" -DCMAKE_BUILD_TYPE="RelWithInfo" ..
make
sudo make install
Install CPP-Driver, ensuring that output LIBDIR is specified and PREFIX to prevent copy to /usr/local/lib
following install.
# Manually Install static libcassandra
# Currnet pkg-config Name: cassandra
# Currnet pkg-config Version: 2.17.1
# Currnet pkg-config Requires: libuv
# Currnet pkg-config Requires: openssl
git clone https://github.com/datastax/cpp-driver.git --recursive
mkdir cpp-driver/build && cd cpp-driver/build
# The process is the same for scylladb/cpp-driver and datastax/cpp-driver.
# Cmake will ignore parameters which are not configured.
cmake -DCASS_CPP_STANDARD=17 -DCASS_BUILD_STATIC=ON -DCASS_BUILD_SHARED=ON -DCASS_USE_TIMERFD=ON -DCASS_USE_LIBSSH2=ON -DCASS_USE_ZLIB=ON -DCMAKE_C_FLAGS="-fPIC" -DCMAKE_CXX_FLAGS="-fPIC -Wno-error=redundant-move" -DCMAKE_BUILD_TYPE="RelWithInfo" -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_INSTALL_LIBDIR=lib -DCASS_INSTALL_PKG_CONFIG=ON ..
make # VERBOSE=1 #Optional verbose logging
sudo make install
While debugging, I have set the CMakePreset.json
for ReleaseLibCassandra
and Release
to Unix Makefiles
to view the make
process verbosely and monitor what is being linked and to where (mainly for the issue of the driver not being linked in the final .so
file.), but present also with Ninja
git clone https://github.com/he4rt/scylladb-php-driver.git --recursive;
# Driver dependant commands:
## Scylladb
cmake --preset Release -DPHP_SCYLLADB_LIBUV_STATIC=ON && cd out/Release
## DS
cmake --preset ReleaseLibCassandra -DPHP_SCYLLADB_USE_LIBCASSANDRA=ON -DPHP_SCYLLADB_LIBUV_STATIC=ON && cd out/ReleaseLibCassandra
# Build dependant command:
## Ninja
sudo ninja install
## Unix Makefiles
make # VERBOSE=1 # Optional verbose logging
sudo make install
# Install .ini file
echo "extension=cassandra.so" | sudo tee -a $(php-config --ini-dir)/cassandra.ini
Finally. To ensure that the library is correctly linked afterwards, and that the system has found the installed extension, run sudo ldconfig
to ensure paths are refreshed.
Check module is loaded with php -m
and check that libcassandra
in linked in the cassandra.so
extension with sudo ldd $(php-config --extension-dir)/cassandra.so
A quick update on reproducing the issue.
<?php
$cluster = [
'name' => 'test_cluster',
'username' => 'cassandra',
'password' => 'cassandra',
'hosts' => ['cassandra-n1', 'cassandra-n2'],
'keyspace' => 'system',
'port' => 9042,
];
$_cluster = Cassandra::cluster()
->withContactPoints('127.0.0.1')
->withPort(9042)
->withCredentials($cluster['username'],$cluster['password'])
->withConnectTimeout(30)
->withRetryPolicy(new \Cassandra\RetryPolicy\DefaultPolicy())
->build();
$session = $_cluster->connect('system');
$statement = new Cassandra\SimpleStatement(
'SELECT * FROM system.sstable_activity_v2 LIMIT 30'
);
$querySent = $session->execute($statement);
//var_dump(get_class_methods($_cluster), "Cluster");
//var_dump(get_class_methods($session), "Session");
// exit;
$i = 0;
foreach($querySent as $row)
{
echo ++$i ."\n";
}
//$i = 0;
//while($i < $querySent->count())
//{
// echo ++$i . "\n";
// $querySent->next();
//}
With this script, if you uncomment both of the var_dump
lines, it produces the ref_count
error message. However, uncommenting and var_dumping one at a time runs fine.
The foreach
and while
loops however, (without the var_dumps being present) will run, but both end in a segfault
ciaran@test-server:/home/ciaran/test$ php test.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Segmentation fault
I have noticed that var_dumps seem to cause a lot of segmentation faults on various attributes while I've been inching my way through the code to find which specific call is causing the ref_count
issue. But the issue seems to be on the teardown process once data has finished being returned.
Thanks for the scripts and how to reproduce, this is fenomenal description, I dont have time until the weekend this week, I'll have to focus on some other Scylla stuff before I get permission to work on the driver. If you @DanielHe4rt can try to reproduce this issue with the example script and send me the results, that would be fantastic, if you are not able, same as me, I'll do it this weekend. Hope @ciaran-moore it's not late for you and a big deal breaking right now
I have noticed that var_dumps seem to cause a lot of segmentation faults on various attributes while I've been inching my way through the code to find which specific call is causing the
ref_count
issue. But the issue seems to be on the teardown process once data has finished being returned.
Yes, this looks like a shutdown issue, and also the overriden get_properties method which is used in var_dump
When I install the extension to use the Datastax CPP-Driver, I receive the error
undefined symbol: cass_session_new
when trying to use the extension.The installs are finding the correct headers as I can see the version info in the cassandra.h file as:
And the extension build shows the version found as:
I can also see the symbol in the header being called and assigned to a CassSession*
Install Steps:
Both build compile successfully, and cassandra module is loaded within
php -m
with no warningsPHP Test Script
Run test script
Any ideas why this would be happening?