fork-helper icon indicating copy to clipboard operation
fork-helper copied to clipboard

Warning: shmop_open(): unable to attach or create shared memory segment 'No space left on device'

Open Moskito89 opened this issue 5 years ago • 7 comments

This problem still exists in v2.3.0. I was playing around with the sample code here and also had some errors and Exceptions, made by my own. When receiving those the script finishes without calling the cleanup() method. I belive that this causes the problem.

Moskito89 avatar Jun 06 '19 11:06 Moskito89

So the problem only occurs when throwing exceptions? I think I can see how that would happen, I'll take a look at reproducing and resolving

duncan3dc avatar Jun 08 '19 10:06 duncan3dc

Hmm I'm unable to reproduce the problem, please can you provide a script that demonstrates the issue?

duncan3dc avatar Jun 08 '19 10:06 duncan3dc

image

FredPeal avatar Jul 09 '19 18:07 FredPeal

So here is the code to reproduce:

<?php 
    
require 'vendor/autoload.php';

use duncan3dc\Forker\Fork;

$fork = new Fork();
$fork->call(function () {
    for ($i = 1; $i <= 3; $i++) {
        echo "Process A - " . $i . "\n";
        sleep(1);
    }
});
$fork->call(function () {
    for ($i = 1; $i < 3; $i++) {
        echo "Process B - " . $i . "\n";
        sleep(1);
    }
});

throw new Exception();

sleep(1);
echo "Waiting for the threads to finish...\n";
$fork->wait();
echo "End\n";

Running this code for 10 to 20 times will end in a Exception Unable to open the shared memory block thrown by the SharedMemory class. When calling $ ipcs -m you will see that there are a lot of segments left. I believe this comes because the exception prevents the Adapter running the cleanup() method which would delete the shared memory instances. So this problem could be solved by adding a shutdown function. Hope it's clearer now :-)

Moskito89 avatar Jul 17 '19 11:07 Moskito89

Hi @Moskito89, you'll need a try/catch around your code to make sure you call $fork->wait().

Right now when a thread ends we don't know if others are still running, so we don't know when it's safe to clean up the shared memory, only the $fork->wait() call tells us.

Another option would be to refactor so that everything is done in $fork->call() calls and then the next thing called is $fork->wait(), if you do anything between $fork->call() and $fork->wait() then you run the risk of leaving the shared memory (as you are seeing)

duncan3dc avatar Jul 18 '19 09:07 duncan3dc

I understand this logic and the problem behind it. But if we'd use a shutdown function we could get sure, that the execution of this script always clears the shared memory, even when the execution fails/exits at some place. Wouldn't it be useful that way? If you don't think so feel free to close this topic :-)

Moskito89 avatar Jul 18 '19 09:07 Moskito89

I'd expect the shutdown function would be called within the threads too, thus deleting the shared memory early. You could perhaps register one after calling $fork->call() in your code.

I'll leave the issue open for now, and try out a few things when I get some time :+1:

duncan3dc avatar Jul 18 '19 09:07 duncan3dc