-
-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
undefined symbol: cass_session_new when installing with libcassandra #106
Comments
This looks like to me it cannot find cassandra.so -> PHP Driver and not libcassandra.so (the datastax driver) Few suggestions to fix the issue
|
Apologies 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 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
Switching users was still providing the PHP Startup Warning
However, expecting this was a linking issue. Doing 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 |
Okay, it looks like an issue maybe with Debian 12?
|
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 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 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 ([email protected]) |
Okay, so step by step detail from building the VPS are as follows. InstanceMachine configurationMachine type | n2-custom-4-2048 Bootable Disk in Google Cloud ConsoleSingle Region, 40GB SSD Install System Pre-RequisitesOnce disk is created and instance is loaded, copy install script and run with php-version as parameter:
Debian12 install.sh#!/bin/bash
# Default value for DEB_VERSION (optional)
PHP_VERSION=""
# Parse command-line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
-p|--php_version)
PHP_VERSION="$2"
shift 2
;;
*)
echo "Usage: $0 -p <php_version> "
exit 1
;;
esac
done
# Ensure both PHP_VERSION and NODE are provided
if [[ -z "$PHP_VERSION" || -z "$NODE" ]]; then
echo "Error: Option -p <php_version> is required."
echo "Usage: $0 -p 8.3"
exit 1
fi
INSTALL_DIR=/home/ciaran
WORKSPACE_DIR=/mnt/workspace_v2
APP_DIR=/mnt/app
# Output provided values
echo "PHP Version: $PHP_VERSION"
##################################################################################
# Update sources, and install base packages. #
# We will run `apt upgrade` after the php repository #
# is added, this way, the dependancy packages which we #
# install here, will also be upgraded to their latest #
# versions #
##################################################################################
mkdir -p $WORKSPACE_MOUNT
mkdir -p $APP_MOUNT
echo "Updating System"
apt update -y > /dev/null 2>&1
# Install base packages
echo
echo "===================================================="
echo "= Installing Base Packages ="
echo "===================================================="
echo
for APP in apt-transport-https apache2 autoconf brotli build-essential ca-certificates cmake curl dirmngr \
fonts-liberation gcc gconf-service git gnupg gzip libappindicator1 libasound2 libassuan-dev libatk1.0-0 \
libbrotli-dev libc-dev libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 \
libgdk-pixbuf2.0-0 libglib2.0-0 libgmp-dev libgpg-error-dev libgpgme11-dev libgtk-3-0 libkrb5-dev libmcrypt-dev \
libstdc++6 libmemcached-dev libnghttp2-dev libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 librdkafka1 \
libssl-dev libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 \
libxi6 libxml2-dev libxrandr2 libxrender1 libxss1 libxtst6 libz-dev lsb-release make memcached nghttp2 ninja-build \
ntp openssl pkg-config python3 python3-pip rsync software-properties-common sshpass sudo unzip wget xdg-utils \
zlib1g zlib1g-dev; do
echo "Installing $APP..."
apt install $APP -y > /dev/null 2>&1
done
AUTOUPDATE=$(which autoupdate) # Required for WDDX Extension
echo "Libraries Installed"
echo
echo "===================================================="
echo "= Installing PHP ="
echo "===================================================="
echo
echo
echo '########################################'
echo '# Install PHP & Modules #'
echo '########################################'
echo
echo "Installing PHP & Modules"
echo
wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php.list
apt update -y > /dev/null 2>&1
apt upgrade -y > /dev/null 2>&1
echo "Installing PHP"
apt install php$PHP_VERSION php$PHP_VERSION-common php$PHP_VERSION-cli php$PHP_VERSION-dev php-pear -y > /dev/null 2>&1
# Install PHP Extensions
echo "Installing PHP Extensions"
#Available Mods found here '/etc/php/$PHP_VERSION/mods-available'
for APP in php$PHP_VERSION-bcmath php$PHP_VERSION-bz2 php$PHP_VERSION-curl php$PHP_VERSION-common php$PHP_VERSION-dom php$PHP_VERSION-gd php$PHP_VERSION-gmp php$PHP_VERSION-gnupg \
php$PHP_VERSION-igbinary php$PHP_VERSION-intl php$PHP_VERSION-imap php$PHP_VERSION-mbstring php$PHP_VERSION-mcrypt php$PHP_VERSION-memcached php$PHP_VERSION-mongodb \
php$PHP_VERSION-msgpack php$PHP_VERSION-mysql php$PHP_VERSION-redis php$PHP_VERSION-pspell php$PHP_VERSION-protobuf php$PHP_VERSION-rdkafka php$PHP_VERSION-ssh2 php$PHP_VERSION-soap php$PHP_VERSION-xml \
php$PHP_VERSION-xsl php$PHP_VERSION-zip; do
echo "Installing $APP..."
apt-get install $APP -y --no-install-recommends > /dev/null 2>&1
done
# Compile gnupg extension
echo "Compile BROTLI extension"
printf '\n' | pecl install -f brotli > /dev/null 2>&1
echo "Create BROTLI Extension file"
echo "extension=brotli.so" | sudo tee -a /etc/php/$PHP_VERSION/mods-available/brotli.ini
# Link BROTLI Extension in CLI / Apache
ln -s /etc/php/$PHP_VERSION/mods-available/brotli.ini /etc/php/$PHP_VERSION/cli/conf.d/20-brotli.ini
ln -s /etc/php/$PHP_VERSION/mods-available/brotli.ini /etc/php/$PHP_VERSION/apache2/conf.d/20-brotli.ini
echo "Extension files linked"
EXT_DIR=$(php-config --extension-dir)
# Install WDDX extension
echo "Install WDDX extension"
echo "Get WDDX -> GIT"
wget https://github.com/php/pecl-text-wddx/archive/master.zip -O $INSTALL_DIR/wddx.zip > /dev/null 2>&1
echo "Unpacking Wddx Zip"
unzip wddx.zip > /dev/null 2>&1
cd pecl-text-wddx-master
echo "Build WDDX "
phpize > /dev/null 2>&1
$AUTOUPDATE
./configure > /dev/null 2>&1
make > /dev/null 2>&1
echo "Installing WDDX from Source"
make install > /dev/null 2>&1
echo "Create WDDX Extension ini"
echo "extension=wddx.so" | sudo tee -a /etc/php/$PHP_VERSION/mods-available/wddx.ini
# Link WDDX Extension in CLI / Apache
ln -s /etc/php/$PHP_VERSION/mods-available/wddx.ini /etc/php/$PHP_VERSION/cli/conf.d/20-wddx.ini
ln -s /etc/php/$PHP_VERSION/mods-available/wddx.ini /etc/php/$PHP_VERSION/apache2/conf.d/20-wddx.ini
echo "Extension files linked"
cd $INSTALL_DIR
rm -Rf $INSTALL_DIR/pecl-text-wddx-master $INSTALL_DIR/wddx.zip
echo
echo '###########################################'
echo '# ALLOW RSA LOGIN ON NEWER DEBIAN INSTALL #'
echo '###########################################'
echo
echo "PubkeyAcceptedAlgorithms ssh-rsa,rsa-sha2-512,rsa-sha2-256" | sudo tee -a /etc/ssh/sshd_config
echo "HostkeyAlgorithms ssh-rsa,rsa-sha2-512,rsa-sha2-256" | sudo tee -a /etc/ssh/sshd_config
Install Cassandra ExtensionThis process is run manually with copy/paste rather than scripted to ensure that each command is running as it should. Install Lib UV ExtensionManually install the libuv library to ensure library is compiled with # 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-DriverInstall CPP-Driver, ensuring that output LIBDIR is specified and PREFIX to prevent copy to # 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 Install PHP ExtensionWhile debugging, I have set the 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 Check module is loaded with |
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 The
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 |
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 |
Yes, this looks like a shutdown issue, and also the overriden get_properties method which is used in |
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?
The text was updated successfully, but these errors were encountered: