Skip to content

Fork kills connection? #195

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

Closed
polonskiy opened this issue Nov 10, 2015 · 6 comments
Closed

Fork kills connection? #195

polonskiy opened this issue Nov 10, 2015 · 6 comments

Comments

@polonskiy
Copy link

Code:

<?php

$memcached = new Memcached;
$memcached->addServer('localhost', 11211);
$memcached->set('foo', 'bar');

var_dump($memcached->get('foo'), $memcached->getResultMessage());

if (!pcntl_fork()) {
    //child process
    die;
}
pcntl_wait($_);

var_dump($memcached->get('foo'), $memcached->getResultMessage());

Output:

PHP 5.5.9-1ubuntu4.14 (cli) (built: Oct 28 2015 01:34:46) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies

ii  libmemcached10:amd64            1.0.8-1ubuntu2                   amd64        C and C++ client library to the memcached server
ii  memcached                       1.4.14-0ubuntu9                  amd64        A high-performance memory object caching system
ii  php5-memcached                  2.1.0-6build1                    amd64        memcached extension module for PHP5, uses libmemcached

string(3) "bar"
string(7) "SUCCESS"
bool(false)
string(9) "NOT FOUND"
PHP 5.6.4-4ubuntu6.4 (cli) (built: Oct 28 2015 01:21:29) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies

ii  libmemcached11:amd64       1.0.18-4                     amd64        C and C++ client library to the memcached server
ii  memcached                  1.4.14-0ubuntu9              amd64        A high-performance memory object caching system
ii  php5-memcached             2.2.0-2build1                amd64        memcached extension module for PHP5, uses libmemcached

string(3) "bar"
string(7) "SUCCESS"
bool(false)
string(7) "FAILURE"
PHP 5.6.11-1ubuntu3.1 (cli) 
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies

ii  libmemcached11:amd64             1.0.18-4                     amd64        C and C++ client library to the memcached server
ii  memcached                        1.4.24-2ubuntu1              amd64        high-performance memory object caching system
ii  php5-memcached                   2.2.0-2build1                amd64        memcached extension module for PHP5, uses libmemcached

string(3) "bar"
string(7) "SUCCESS"
bool(false)
string(7) "FAILURE"
@Timandes
Copy link
Contributor

Fork dose not kill the connection, die in child process will.

<?php

$memcached = new Memcached;
$memcached->addServer('localhost', 11211);
$memcached->set('foo', 'bar');

var_dump($memcached->get('foo'), $memcached->getResultMessage());

if (!pcntl_fork()) {
    //child process
    sleep(10);
    die;
}
// pcntl_wait($_);

var_dump($memcached->get('foo'), $memcached->getResultMessage());

Result:

string(3) "bar"
string(7) "SUCCESS"
string(3) "bar"
string(7) "SUCCESS"

@polonskiy
Copy link
Author

@Timandes thanks. However, I don't think it is expected behavior.

@polonskiy
Copy link
Author

Memcache (without d) extension works as expected.

Replacing die with one of these also helps:

pcntl_exec('/bin/true');
posix_kill(getmypid(), SIGKILL);
posix_kill(getmypid(), SIGINT);
posix_kill(getmypid(), SIGTERM);

@mkoppanen
Copy link
Member

I can try to see if we can make this safe for forks. Not sure if libmemcached is

@sodabrew
Copy link
Contributor

sodabrew commented Feb 7, 2017

What's happening is that the open connections are all inherited by the child process, but when the child process exits, cleanup begins: PHP calls the destructor functions for the memcached extension, which calls the destructor functions for libmemcached, which sends a quit command to each open memcached connection. https://bazaar.launchpad.net/~tangent-trunk/libmemcached/1.0/view/head:/libmemcached/instance.cc#L167

Because the same connections are being used in the child as in the parent process, when the quit command is sent, the one-and-the-same connection is closed in both parent and child.

Note that because the same connections are being used, you have a risk to corrupt the stream of data to your memcached if the parent and child both try to read/write on the same connections.

An approach to protecting against connection sharing would be to set FD_CLOEXEC on the sockets that libmemcached opens, so that after a fork the sockets are closed in the child. But the server list would still include those socket handles, so the first operation against each server in the child would go through the error/reconnect code path. Ironically, I think, in the destructor code path it might mean a reconnect followed immediately by a quit. Unfortunately I cannot find where in libmemcached I could get access to the file descriptors of the connections to each server in the fist place in order to set the FD_CLOEXEC flag.

So I'm closing this as wont-fix.

@sodabrew sodabrew closed this as completed Feb 7, 2017
@Jurigag
Copy link

Jurigag commented Feb 21, 2020

Sorry for asking after 3 years, but im hardly stuggling with it. We have cron manager which forks processes and then we access keys and stores them on using php-memcached and we have many weird issues like wrong values returned, empty values etc, totally random and unstable behavior. What we had after fork was exit(1), was trying to replace it with any of the:

pcntl_exec('/bin/true');
posix_kill(getmypid(), SIGKILL);
posix_kill(getmypid(), SIGINT);
posix_kill(getmypid(), SIGTERM);

But didn't solve the issue. Also tried to create new connection to memcache after forking a process(read it somewhere) but also doesn't seem to help with this. Does this basically means don't use php-memcached when forking processes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants