Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

robdesilets's avatar

Redis psubscribe not exiting with CTRL-C

Hi All,

I have been using Laravel since version 6, and upgrade as new versions come out. I am running Laravel 10, latest update. I am using predis.

I have a long running process that subscribes to redis, per the Laravel documentation. Here is a test program I wrote:

use Illuminate\Console\Command; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Redis;

class Test extends Command {

protected $signature = 'development:test';
protected $description = 'Test';

public function handle()
{
    
    Redis::psubscribe(['foo.*'], function ($message, $channel) {
        Log::debug("in here");
    });
}

}

I used to be able to CTRL-C on my Mac and it would kill the process, which I think is sig INT. It stopped working like that and CTRL-C in the terminal no longer stops the process, I actually have to find the PID and kill it.

I am seeing this same behavior in our production environment, supervisor keeps this process running. When I restart supervisor it use to instantly return me to the prompt (presumably because it send an sig INT to this command which immediately exited).

Now supervisor takes a really long time to restart, my guess is that it times out and eventually kills the process like I do on my dev box.

I can't tell if this changed when I upgraded to Laravel 10, or a recent update to Laravel 10, or maybe a predis update.

Any ideas would be greatly appreciated.

Thanks!

0 likes
3 replies
LaryAI's avatar
Level 58

The issue might be related to the fact that Redis connections are persistent by default. You can try setting the persistent option to false when creating the Redis client instance. Here's an updated version of the handle method:

public function handle()
{
    $redis = Redis::connection(['persistent' => false]);
    $redis->psubscribe(['foo.*'], function ($message, $channel) {
        Log::debug("in here");
    });
}

This should allow the process to exit gracefully when you press CTRL-C.

robdesilets's avatar

Thanks for the reply. I tried that and it did not seem to work. I added the parameter to the database configuration and put a log in the predis client and confirmed the value was getting into the client.

As I mentioned I remember this use to work fine (I would have noticed CTRL-C did not quit as when I was originally building the system I would CTRL-C many times per day). Since it's been a while since I made a change I did not run locally for a while, but today I did and noticed it and also did some investigation to find the supervisor was hanging in restart as well.

'read_write_timeout' => -1, 'persistent' => 0

robdesilets's avatar

I did some more testing today and it seems like when psubscribe is running the command does not even receive the SIGINT signal.

When I hit CTRL C when the while(true) is running the command exits.

When I hit CTRL C when the psubscribe is running my console just shows ^C but the program never actually exits until I kill it.

I am sure this use to work but I don't know what changed that could cause this behavior. I think that anyone that is running psubscribe in the long running process (per Laravel docs) would be hitting this.

I am on Laravel 10 (lates), Redis 6 (latest), Php 8.2 (latest).

class Test extends Command implements SignalableCommandInterface {

protected $signature = 'development:test';
protected $description = 'Test'; 

public function handle()
{
    // when this is running handleSignal is called and the command exits
    while (true) {
        sleep(5);
    }

    // when this is running handleSignal is never called and the command never exits
    Redis::psubscribe(['system.*'], function ($message, $channel) {
        Log::debug("in psubscribe");
        
    });
}

public function getSubscribedSignals(): array
{
    return [SIGINT, SIGTERM];
}

public function handleSignal(int $signal): void
{
    if ($signal === SIGINT) {
        Log::debug("SIGINT bye");
        exit;
    }
    if ($signal === SIGTERM) {
        Log::debug("SIGTERM bye");
        exit;
    }
}

}

Please or to participate in this conversation.