A PHP extension for Redis
Other
9624
473
2125

Expected behaviour

connect(} now and use later.

Actual behaviour

If not used immediately after connect() tls:// connection hangs when used later.

I'm seeing this behaviour on

  • OS: Ubuntu 20.04
  • Redis: 6.0.16
  • PHP: 8.1, 8.2
  • phpredis: 5.3.5+

Steps to reproduce, backtrace or example script

$host = 'localhost';
$port = 6379;
$tls_opts = ['verify_peer' => false, 'verify_peer_name' => false];

$timeout = 1;

$client = new Redis();
if (!$client->connect("tls://$host", $port, 0, null, 0, 0, ['stream' => $tls_opts])) {
    throw new Exception('Unable to connect to host.');
}

// $client->ping(); // If uncommented it works, otherwise hangs

sleep($timeout);
$client->ping();

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

When use xGroup on cluster and got "Next RedisClusterException: Can't communicate with any node in the cluster"
I see cluster_library.h and not found commands with xGroup .xReadGroup and so on.

My redis info:
redis 7.0

cluster inf
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:1
cluster_size:1
cluster_current_epoch:1
cluster_my_epoch:1
cluster_stats_messages_sent:0
cluster_stats_messages_received:0
total_cluster_links_buffer_limit_exceeded:0

cluster slots
1) 1) (integer) 0
   2) (integer) 16383
   3) 1) ""
      2) (integer) 6379
      3) "eaeb72c0c2093cf7cc047058ad6221c02c9e12b9"
      4) (empty array)

Hello,

This is just a simple issue report on other Java, Python, ectera client redis libraries that are known and we have seen have problems especially regarding "Sessions getting mixed up between different users". Although this would affect non-sessions too.

We have seen this issue happen to several large Java based sites, and we think we have finally figured the exact reason due to recent OpenAPI outage.

Here is OpenAPI describing the issue(redis-py, python based redis client):
https://openai.com/blog/march-20-chatgpt-outage

Here is the (suspected) bug happening on Java based client library too:
redisson/redisson#4747

This issue is opened to suggest phpredis developers check whether the phpredis library is susceptible a similar issue as "Sessions getting mixed up between different users".
Especially when using persistent redis connections.
As I confirmed or suspect this happening in other Java and Python redis client libraries, I suggest phpredis check whether it is also susceptible to similar bug.

OpenAPI described the bug as the following when is occured for redis-py:

  • The library maintains a shared pool of connections between the server and the cluster, and recycles a connection to be used for another request once done.
  • When using Asyncio, requests and responses with redis-py behave as two queues: the caller pushes a request onto the incoming queue, and will pop a response from the outgoing queue, and then return the connection to the pool.
  • If a request is canceled after the request is pushed onto the incoming queue, but before the response popped from the outgoing queue, we see our bug: the connection thus becomes corrupted and the next response that’s dequeued for an unrelated request can receive data left behind in the connection.
  • In most cases, this results in an unrecoverable server error, and the user will have to try their request again.
  • But in some cases the corrupted data happens to match the data type the requester was expecting, and so what gets returned from the cache appears valid, even if it belongs to another user.

Thank you.

Redis 7.2-RC1 is released

From 00-RELEASENOTES

New user commands or command arguments

  • WAITAOF blocks until writes have been synced to disk (#11713)
  • Add WITHSCORE option to ZRANK and ZREVRANK (#11235)

New administrative and introspection commands and command arguments

  • CLIENT SETINFO lets client library report name and version Redis (#11758)
  • CLIENT NO-TOUCH for clients to run commands without affecting LRU/LFU of keys (#11483)

Command replies that have been extended

  • ACL LOG - Add entry id, timestamp created, and timestamp last updated time (#11477)
  • COMMAND DOCS - Repurpose arg names as the unique ID (#11051)
  • CLIENT LIST has T flag to indicate CLIENT NO-TOUCH (#11483)
  • CLIENT LIST show lib-name, lib-ver (#11758)

Expected behaviour

Redis documentation for the SELECT command says that

New connections always use the database 0

So subsequent SELECT commands on different connections should not change the database number for other connections, even if the database 0 was not explicitly selected.

And if the database for connection was changed for any reason, Redis::getDbNum() method should return database number being used.

Actual behaviour

I have the following script which runs in PHP-FPM:

<?php

$redis0 = new Redis();
$redis0->pconnect('redis', 6379, 0.0, 'redis0');
# No explicit select 0 here

$redis1 = new Redis();
$redis1->pconnect('redis', 6379, 0.0, 'redis1');
$redis1->select(1);

$redis2 = new Redis();
$redis2->pconnect('redis', 6379, 0.0, 'redis2');
$redis2->select(2);

echo $redis0->getDbNum();
$redis0->set('REDIS_0', '0');

echo $redis1->getDbNum();
$redis1->set('REDIS_1', '1');

echo $redis2->getDbNum();
$redis2->set('REDIS_2', '2');

On the first and second requests the keys appear in correct databases (MONITOR output from redis-cli):

# Request 1
1611942079.015152 [0 172.18.0.9:45512] "SELECT" "1"
1611942079.016807 [0 172.18.0.9:45514] "SELECT" "2"
1611942079.017168 [0 172.18.0.9:45510] "SET" "REDIS_0" "0"
1611942079.017464 [1 172.18.0.9:45512] "SET" "REDIS_1" "1"
1611942079.017689 [2 172.18.0.9:45514] "SET" "REDIS_2" "2"

1611942219.691163 [2 172.18.0.1:47622] "flushall" # flushall from redis-cli

# Request 1
1611942223.955243 [0 172.18.0.9:45592] "SELECT" "1"
1611942223.955885 [0 172.18.0.9:45594] "SELECT" "2"
1611942223.956078 [0 172.18.0.9:45590] "SET" "REDIS_0" "0"
1611942223.956166 [1 172.18.0.9:45592] "SET" "REDIS_1" "1"
1611942223.956259 [2 172.18.0.9:45594] "SET" "REDIS_2" "2"

Checking the keys in redis-cli:

127.0.0.1:63799> keys *
1) "REDIS_0"
127.0.0.1:63799> select 1
OK
127.0.0.1:63799[1]> keys *
1) "REDIS_1"
127.0.0.1:63799[1]> select 2
OK
127.0.0.1:63799[2]> keys *
1) "REDIS_2"

However, on the third request (without flushall between requests) the "REDIS_0" key appears in the database 2:

1611942329.811933 [2 172.18.0.9:45514] "ECHO" "phpredis:601449b9c6073:1867ae6f"
1611942329.812692 [1 172.18.0.9:45512] "ECHO" "phpredis:601449b9c6586:3eac0768"
1611942329.813386 [1 172.18.0.9:45512] "SELECT" "1"
1611942329.813804 [0 172.18.0.9:45510] "ECHO" "phpredis:601449b9c6a0c:1bb3c7f6"
1611942329.814144 [0 172.18.0.9:45510] "SELECT" "2"
1611942329.814439 [2 172.18.0.9:45514] "SET" "REDIS_0" "0"
1611942329.814647 [1 172.18.0.9:45512] "SET" "REDIS_1" "1"
1611942329.814945 [2 172.18.0.9:45510] "SET" "REDIS_2" "2"

Checking the keys:

127.0.0.1:63799> keys *
1) "REDIS_0"
127.0.0.1:63799> select 1
OK
127.0.0.1:63799[1]> keys *
1) "REDIS_1"
127.0.0.1:63799[1]> select 2
OK
127.0.0.1:63799[2]> keys *
1) "REDIS_2"
2) "REDIS_0"

Meanwhile, during all the requests $redisN->getDbNum(); outputs correct database numbers: 0 1 2.

I'm seeing this behaviour on

  • OS: Linux 5.10.9-201.fc33.x86_64 x86_64 (redis docker image)
  • PHP: 7.4.13
  • Redis: 6.0.8
  • phpredis: 5.3.2

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch - not sure how do I check that

Actual behaviour (Problem)

I'm trying to use redis as a Pub/Sub system. I can subscribe to a channel and post messages to it. The problem is when I try to exit the callback and return to the general context of my class. I tried several alternatives, I read in some forums that the right thing to do is to work with the return, returning false Redis should stop the continuous execution of the callback and return the context, but that doesn't happen. I can't even stop PHP execution during script execution, it blocks events like exit and exceptions.

I'm seeing this behaviour on

  • OS: Ubuntu 22.04.1 LTS
  • Redis: 5.3.7
  • PHP: PHP 8.1.15
  • phpredis: 5.3.3

Steps to reproduce, backtrace or example script

For testing, I split a test into a separate flat file.

publish.php

$redis = new Redis();
$redis->connect('redis', 6379);
$redis->auth('pass');

$redis->publish('channel.test', 'quit');

subscribe.php

$redis = new Redis();
$redis->connect('redis', 6379);
$redis->auth('pass');

$redis->subscribe(['channel.test'], function ($redis, $channel, $message) {
    echo "Received message: $message\n";
    if ($message === 'quit') {
        $redis->unsubscribe(['channel.test']);
    }
});

echo "Exited subscribe loop\n";

But when I send a second message in a row in the publish.php code the callback works as expected.

Changes on publish.php

# [...]
$redis->publish('devops.teste', 'quit');
$redis->publish('devops.teste', 'confirm-message');

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

The redis session handler does not support sentinel. It is not usable for High Availability.

Add sentinel support with a retry mechanism when master dies till slave is promoted to master.

php Redis working in localhost

ini_set("display_errors",1);
error_reporting(E_ALL);
ini_set("default_socket_timeout", -1);

$objRedis = new Redis();

try{
$con = $objRedis->connect('localhost',8088);
if (!$con) {
throw new Exception('Failed');
}else{
echo "Connected with Server";
}
} catch (Exception $e) {
die($e->getMessage());
}
$objRedis->set('Kitchen_api_Key','Hello Cloud');
echo $objRedis->get('Kitchen_api_Key');

$objRedis -> del('Kitchen_api_Key');

if($objRedis->exists('Kitchen_api_Key')) echo " Key exist";
else echo " Key not exist";

$objRedis->close();
exit;

I am changing the host, connection is establishing but i am getting Fatal error: Uncaught RedisException: read error on connection to

ini_set("display_errors",1);
error_reporting(E_ALL);
ini_set("default_socket_timeout", -1);

$objRedis = new Redis();

try{
$con = $objRedis->connect('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.ondigitalocean.com',12345);
if (!$con) {
throw new Exception('Failed');
}else{
echo "Connected with Server";
}
} catch (Exception $e) {
die($e->getMessage());
}
$objRedis->set('Kitchen_api_Key','Hello Cloud');
echo $objRedis->get('Kitchen_api_Key');

$objRedis -> del('Kitchen_api_Key');
OUTPUT

if($objRedis->exists('Kitchen_api_Key')) echo " Key exist";
else echo " Key not exist";

$objRedis->close();
exit;

OUTPUT

Connected with Server

Fatal error: Uncaught RedisException: read error on connection to
XXXXXXXXXXXXXXXXXXXXXXXXXX.ondigitalocean.com:12345 in /var/www/html/asd/redis.php:22
Stack trace:
#0 /var/www/html/asd/redis.php(22): Redis->set()
#1 {main}
thrown in /var/www/html/asd/redis.php on line 22

Expected behaviour

I am using PHPRedis to connect to a single Redis node. I want to save sessions there. It works for Redis Cluster, however session_start() won't work in single node mode.

Actual behaviour

My connection string is the following:

<?php

// Register REDIS Session Handler using REDIS PHP Module
ini_set('session.save_handler','redis');
ini_set('session.save_path', "tls://redis:6379?prefix=D9E47SESSION/DATA/&timeout=2&auth=the-strong-one&stream[local_cert]=/server/tls/client.crt&stream[local_pk]=/server/tls/client.key&stream[cafile]=/server/tls/ca.crt&stream[verify_peer_name]=0");

Similar code works with the Redis Cluster, but the stream params seem not to work with a single Redis node. Are there errors in my connection string?

I'm seeing this behaviour on

  • OS: Centos 7
  • Redis: 6.2
  • PHP: 8.0.25
  • phpredis: 5.3.7

I've checked

  • There is no similar issue from other users

Expected behaviour

Find a downloadable DLL for running Redis on Windows with PHP 8.2 at https://windows.php.net/downloads/pecl/releases/redis/5.3.7/

Actual behaviour

Only PHP 8.1 and lower are here.

I'm seeing this behaviour on

  • OS: Windows
  • Redis: 5.3.7
  • PHP: 8.2
  • phpredis: N/A

Steps to reproduce, backtrace or example script

N/A

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

Expected behaviour

The Redis server requires TLS, and trying to set up phpredis with Laravel over TLS, but getting this error:

Redis::connect(): SSL operation failed with code 1. OpenSSL Error messages:
error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed {"exception":"[object] (ErrorE
xception(code: 0): Redis::connect(): SSL operation failed with code 1. OpenSSL Error messages:
error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed at /vendor/lara
vel/framework/src/Illuminate/Redis/Connectors/PhpRedisConnector.php:141)

and this is my config:

redis' => [
        'client' => env('REDIS_CLIENT', 'phpredis'),
        'options' => [
            'cluster' => env('REDIS_CLUSTER', 'redis'),
            'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
            'ssl' => ['verify_peer' => false,  'cafile' => file_get_contents(env('REDIS_PEM_FILE'))],
        ],
        'default' => [
            'scheme' => 'tls',
            'url' => env('REDIS_URL'),
            'host' => env('REDIS_HOST', '127.0.0.1'),
            'password' => env('REDIS_PASSWORD', null),
            'port' => env('REDIS_PORT', '6379'),
            'database' => env('REDIS_DB', '0'),
        ],
]

Not sure how to fix that. Appreciate for any help.

Expected behaviour

Test should pass

Actual behaviour

Assertion failed (Array
(
)
 !== ): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:4987 (testNullArray)
Assertion failed (Array
(
    [0] => Array
        (
        )

)
 !== Array
(
    [0] => 
)
): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:4992 (testNullArray)
Assertion failed ( !== ): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:4987 (testNullArray)
Assertion failed (Array
(
    [0] => 
)
 !== Array
(
    [0] => 
)
): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:4992 (testNullArray)
Assertion failed (Array
(
    [0] => Array
        (
        )

    [1] => Array
        (
        )

)
 !== Array
(
)
): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:5004 (testNestedNullArray)
Assertion failed (Array
(
    [0] => Array
        (
            [0] => Array
                (
                )

            [1] => Array
                (
                )

        )

)
 !== Array
(
    [0] => Array
        (
        )

)
): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:5008 (testNestedNullArray)
Assertion failed (Array
(
    [0] => 
    [1] => 
)
 !== Array
(
)
): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:5004 (testNestedNullArray)
Assertion failed (Array
(
    [0] => Array
        (
            [0] =>
            [1] =>
        )

)
 !== Array
(
    [0] => Array
        (
        )

)
): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:5008 (testNestedNullArray)
Assertion failed: /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:6140 (testXInfoEmptyStream)
Assertion failed (0 !== ): /usr/src/rpmbuild/BUILD/php-pecl-redis-5.3.4/NTS/tests/RedisTest.php:6141 (testXInfoEmptyStream)

I'm seeing this behaviour on

  • OS: CentOS 7
  • Redis: 3.2.12
  • PHP: 7.4.20
  • phpredis: 5.3.4

Steps to reproduce, backtrace or example script

I'm using a modified version of the Fedora spec file to build the extension (attached).
I use the same spec file for phpredis 5.2.2 (only modifying the version) and that one builds fine.

php-pecl-redis.spec.txt

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

Expected behaviour

When attempting to update the score of a member with the GT flag, the score should not be updated unless the score is greater than the existing score.

Actual behaviour

The score is updated when it should not be, even though 0 is returned by phpredis indicating no records should have been updated.

I'm seeing this behaviour on

  • OS: Mac / Linux
  • Redis: 7.0
  • PHP: 8.2
  • phpredis: 5.3.7

Steps to reproduce, backtrace or example script

$redis->zadd('example-key', 100, 'example-member');
$redis->zadd('example-key', ['GT'], 1, 'example-member');

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

Expected behaviour

throw redis exception

Actual behaviour

return FALSE

I'm seeing this behaviour on

  • OS: centos 6.9
  • Redis:3.2.3
  • PHP:7.1.7
  • phpredis:3.1.3

Steps to reproduce, backtrace or example script

when the redis connected
and network not good.
sending cmd or reciveing
network down
phpredis will return false
not throw exception

I've checked

  • There is no similar issue from other users ,

have same but i found a little different

  • Issue isn't fixed in develop branch
    sure

Expected behaviour

PHP Session to be locked and to be writeable.

Actual behaviour

PHP Session fails to lock and write.

I'm seeing this behaviour on

  • OS:
    Ubuntu 16.04.5 LTS on AWS EC2

  • Redis:
    Redis 4.0.10 on AWS Elasticache

  • PHP:
    PHP 7.2.10-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Oct 1 2018 11:45:50) ( NTS )
    Copyright (c) 1997-2018 The PHP Group
    Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.10-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies

  • phpredis:
    redis 4.1.1 stable

Steps to reproduce, backtrace or example script

php.ini:

session.save_handler = redis
session.save_path = "tcp://127.0.0.1:7500?weight=1&timeout=3&auth=password123,tcp://127.0.0.1:7501?weight=1&timeout=3&auth=password123"
redis.session.locking_enabled = 1

stunnel conf:

pid = /var/run/stunnel.pid
debug = 7
delay = yes
options = NO_SSLv2
options = NO_SSLv3
[redis-shard-1]
   client = yes
   accept = 127.0.0.1:7500
   connect = master.xxxxxx.xxxxx.xxxx.cache.amazonaws.com:7500
[redis-shard-2]
   client = yes
   accept = 127.0.0.1:7501
   connect = master.zzzzz.zzzzz.zzzzzz.cache.amazonaws.com:7500

test.php on webserver:

<?php
//simple counter to test sessions. should increment on each page reload.
session_start();
$count = isset($_SESSION['count']) ? $_SESSION['count'] : 1;

echo $count;

$_SESSION['count'] = ++$count;

$_SESSION['token1'] = bin2hex(random_bytes(128/2));
$_SESSION['uuid'] = 492499944;
$_SESSION['timestamp'] = time();
$_SESSION['token2'] = bin2hex(random_bytes(128/2));
?>

If you go to example.com/test.php it works fine sometimes and sometimes it fails to lock and update the session with this error:

==> /var/logs/apache2/error_log.20181011000000 <==
[Fri Oct 12 03:18:59.803737 2018] [php7:notice] [pid 230224] [client 172.31.9.6:6288] PHP Notice:  session_start(): Acquire of session lock was not successful in /www/test.php on line 3
[Fri Oct 12 03:18:59.804534 2018] [php7:warn] [pid 230224] [client 172.31.9.6:6288] PHP Warning:  Unknown: Failed to write session data (redis). Please verify that the current setting of session.save_path is correct (tcp://127.0.0.1:7500?weight=1&timeout=3&auth=password123,tcp://127.0.0.1:7501?weight=1&timeout=3&auth=password123) in Unknown on line 0

I will try without stunnel tomorrow to see if that could be causing the issue.

Do you see any obvious issues with config or log entries?

Thank you

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

Expected behaviour

When calling rPop with the second parameter greater than 0, it needs to decompress and unserialize data.

$redis->rPop($key, $count);

Actual behaviour

When calling rPop with the second parameter greater than 0, it returns raw data, without unserializing and decompressing it.

I'm seeing this behaviour on

  • docker: 'bitnami/redis:7.0.5'
  • PHP: 8.1.2-1ubuntu2.9
  • phpredis: 6.0.0-dev
  • serializer: msgpack
  • compression: lz4

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

Expected behaviour

igbinary support can be enabled without forcing PHP to segfault.

Actual behaviour

When executing any PHP related binary (php, pecl - which internally uses php, etc.), I get instant segfault whenever I enable igbinary + redis extension.

What actually works is using igbinary standalone, igbinary + redis (while not compiling with igbinary support) and redis standalone.

Using igbinary_serialize itself does not give me any errors and thus, I think it is somehow related to phpredis compiling in the igbinary stuff.

I'm seeing this behaviour on

  • OS: Mac OS Ventura
  • Redis: -
  • PHP: 7.4.32
  • phpredis: 5.3.7

Steps to reproduce, backtrace or example script

pecl install -f igbinary redis --configureoptions 'enable-redis-igbinary="yes" enable-redis-lzf="no" enable-redis-zstd="no"'
php -m | egrep "redis|igbinary"

This already gives me Killed: 9 on bash.

I've checked out develop as well and there, I at least do not get a segfault:

PHP Warning: PHP Startup: Unable to load dynamic library 'redis.so' (tried: /opt/homebrew/lib/php/pecl/20190902/redis.so (dlopen(/opt/homebrew/lib/php/pecl/20190902/redis.so, 0x0009): symbol not found in flat namespace (_igbinary_serialize)), /opt/homebrew/lib/php/pecl/20190902/redis.so.so (dlopen(/opt/homebrew/lib/php/pecl/20190902/redis.so.so, 0x0009): tried: '/opt/homebrew/lib/php/pecl/20190902/redis.so.so' (no such file))) in Unknown on line 0
Warning: PHP Startup: Unable to load dynamic library 'redis.so' (tried: /opt/homebrew/lib/php/pecl/20190902/redis.so (dlopen(/opt/homebrew/lib/php/pecl/20190902/redis.so, 0x0009): symbol not found in flat namespace (_igbinary_serialize)), /opt/homebrew/lib/php/pecl/20190902/redis.so.so (dlopen(/opt/homebrew/lib/php/pecl/20190902/redis.so.so, 0x0009): tried: '/opt/homebrew/lib/php/pecl/20190902/redis.so.so' (no such file))) in Unknown on line 0

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

Expected behaviour

System does not crash after failover.

Actual behaviour

A failover of Redis Cluster master causes the phpredis extension to crash.

I'm seeing this behaviour on

  • OS: Docker php:7.4-fpm-alpine
  • Redis: 7.0
  • PHP: 7.4.33
  • phpredis: 6.0.0-dev

Steps to reproduce, backtrace or example script

Coredump:

Core was generated by `php-fpm:'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  cluster_update_slot (c=c@entry=0xffffb0a01000) at /root/phpredis/cluster_library.c:1407
1407	            ZEND_HASH_FOREACH_PTR(prev_master->slaves, slave) {
(gdb)
(gdb) bt
#0  cluster_update_slot (c=c@entry=0xffffb0a01000) at /root/phpredis/cluster_library.c:1407
#1  0x0000ffffb984ed28 in cluster_send_command (c=c@entry=0xffffb0a01000, slot=<optimized out>,
    cmd=0xffffbaa62500 "*4\r\n$5\r\nSETEX\r\n$56\r\nsecurity:tok"..., cmd_len=232)
    at /root/phpredis/cluster_library.c:1588
#2  0x0000ffffb98356c8 in zim_RedisCluster_setex (execute_data=0xffffbaa15f10, return_value=0xffffdbfcaee0)
    at /root/phpredis/redis_cluster.c:732

Strace:

socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 18
fcntl(18, F_GETFL)                      = 0x2 (flags O_RDWR)
fcntl(18, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE) = 0
connect(18, {sa_family=AF_INET, sin_port=htons(6379), sin_addr=inet_addr("172.18.0.4")}, 16) = -1 EINPROGRESS (Operation in progress)
ppoll([{fd=18, events=POLLIN|POLLOUT|POLLERR|POLLHUP}], 1, {tv_sec=5, tv_nsec=0}, NULL, 8) = 1 ([{fd=18, revents=POLLOUT}], left {tv_sec=4, tv_nsec=999998833})
getsockopt(18, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
fcntl(18, F_SETFL, O_RDWR|O_LARGEFILE)  = 0
setsockopt(18, SOL_TCP, TCP_NODELAY, [1], 4) = 0
setsockopt(18, SOL_SOCKET, SO_KEEPALIVE, [0], 4) = 0
ppoll([{fd=18, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, {tv_sec=0, tv_nsec=0}, NULL, 8) = 0 (Timeout)
sendto(18, "*4\r\n$5\r\nSETEX\r\n$56\r\nsecurity:tok"..., 232, MSG_DONTWAIT, NULL, 0) = 232
ppoll([{fd=18, events=POLLIN|POLLPRI|POLLERR|POLLHUP}], 1, {tv_sec=0, tv_nsec=0}, NULL, 8) = 1 ([{fd=18, revents=POLLIN}], left {tv_sec=0, tv_nsec=0})
recvfrom(18, "-", 1, MSG_PEEK, NULL, NULL) = 1
ppoll([{fd=18, events=POLLIN|POLLERR|POLLHUP}], 1, {tv_sec=10, tv_nsec=0}, NULL, 8) = 1 ([{fd=18, revents=POLLIN}], left {tv_sec=9, tv_nsec=999998875})
recvfrom(18, "-MOVED 13085 172.18.0.19:6379\r\n", 8192, MSG_DONTWAIT, NULL, NULL) = 31
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x10} ---
+++ killed by SIGSEGV +++

I've checked

  • There is no similar issue from other users
  • Issue isn't fixed in develop branch

Notes

Looking through the code I can see it correctly reacts to receiving the MOVED response from redis cluster and it attempts to updates its internal cache for the slot in cluster_update_slot().

For some reason it fails here:

phpredis/cluster_library.c

Lines 1407 to 1417 in 6b8d682

ZEND_HASH_FOREACH_PTR(prev_master->slaves, slave) {
if (slave == NULL) {
continue;
}
if (!CLUSTER_REDIR_CMP(c, slave->sock)) {
// Detected a failover, the redirected node was a replica
// Remap the cluster's keyspace
cluster_map_keyspace(c);
return;
}
} ZEND_HASH_FOREACH_END();

Expected behaviour

Actual behaviour

I'm seeing this behaviour on

  • OS: Ubuntu 20.04
  • Redis: 6.2.6
  • PHP: 8.1
  • phpredis: 5.3.5

Steps to reproduce, backtrace or example script

I've checked

  • There is no similar issue from other users
  • No issue on develop branch, only on 5.3.5 in combination with PHP 8.1

I get this error when using the Redis 5.3.5 on PHP 8.1 together with ProxyManager to make it lazy.

        $this->getContainer()->get('redis_default_connection')->flushAll();

Reproducer: https://github.com/ruudk/lazy-redis-extension-reproducer

The ProxyManager generates the following code:

    public function flushAll($async = null)
    {
        $this->initializer342a0 && ($this->initializer342a0->__invoke($valueHolder12061, $this, 'flushAll', array('async' => $async), $this->initializer342a0) || 1) && $this->valueHolder12061 = $valueHolder12061;

        return $this->valueHolder12061->flushAll($async);
    }

It doesn't read the type of the $async parameter. So when you call it with flushAll(); it will pass null to the actual extension.

If I generate the code using the redis.stub.php file, it does create a better version:

    public function flushAll(bool $async = false) : bool
    {
        $this->initializer342a0 && ($this->initializer342a0->__invoke($valueHolder12061, $this, 'flushAll', array('async' => $async), $this->initializer342a0) || 1) && $this->valueHolder12061 = $valueHolder12061;

        return $this->valueHolder12061->flushAll($async);
    }

I think this can be solved by adding the the correct type information to all arguments. This way, it can be read using reflection.

Hi,

We are using PHPRedis with Laravel. We push jobs into Redis and our workers pop jobs from it.

Our workers are long running processes which are not supposed to be restarted.

99% of our jobs are popped successfully. However, we sometimes face the following issue when trying to establish the connection, using pconnect:

[2020-11-13 12:52:41] production.ERROR: Operation now in progress {"exception":"[object] (RedisException(code: 0): Operation now in progress at /var/www/html/vendor/illuminate/redis/Connectors/PhpRedisConnector.php:135)
[stacktrace]
#0 /var/www/html/vendor/illuminate/redis/Connectors/PhpRedisConnector.php(135): Redis->pconnect('azure...', '6379', 0, NULL, 0, 0, Array)

I'm seeing this behaviour on

  • OS: Ubuntu-18.04.1
  • Redis: 4.0.14 on Azure (tcp)
  • PHP: 7.4.12
  • phpredis: 5.3.2

Steps to reproduce, backtrace or example script

Very hard to reproduce since it happens only a few times per day (we process around 50K jobs per day).

Any idea of what could go wrong or a way to fix it?