]> git.graph-it.com Git - graphit/concurrent.git/commitdiff
* Removed deprecated chr() #9940 master v0.1.3
authorSebastian Brix <sebastian.brix@graph-it.com>
Wed, 27 May 2026 07:23:55 +0000 (09:23 +0200)
committerSebastian Brix <sebastian.brix@graph-it.com>
Wed, 27 May 2026 07:25:21 +0000 (09:25 +0200)
* Fixed Psalm Warnings
* Removed dead code
* Added DaemonTest.php

composer.json
src/Daemon.php
src/MainThread.php
src/Service.php
src/Thread.php
tests/DaemonTest.php [new file with mode: 0644]

index bf66e118a09ada2ddf37ccd4816d7dc1f84ad3f9..3bd3c0e440c0b6cace834c4b9fb78dd8e3a24743 100644 (file)
@@ -1,20 +1,20 @@
 {
-    "name": "graphit/concurrent",
-    "type": "library",
-    "authors": [
-        {
-            "name": "Graph-IT",
-            "email": "info@graph-it.com"
-        }
-    ],
-    "require": {
-        "php": ">=7.4.0",
-        "ext-pcntl": "*",
-        "ext-posix": "*"
-    },
-    "autoload": {
-        "psr-4": {
-            "Graphit\\Concurrent\\": "src/"
-        }
+  "name": "graphit/concurrent",
+  "type": "library",
+  "authors": [
+    {
+      "name": "Graph-IT",
+      "email": "info@graph-it.com"
     }
-}
+  ],
+  "require": {
+    "php": ">=8.4.0",
+    "ext-pcntl": "*",
+    "ext-posix": "*"
+  },
+  "autoload": {
+    "psr-4": {
+      "Graphit\\Concurrent\\": "src/"
+    }
+  }
+}
\ No newline at end of file
index 420ac13f597ed11d5f5b2790e394189ccc02f944..d3fb50edc226ab409932b66cf794bb138e61158f 100644 (file)
@@ -2,17 +2,19 @@
 
 namespace Graphit\Concurrent;
 
+use RuntimeException;
+
+/** @api */
 abstract class Daemon extends Thread
 {
-  /** */
+  #[\Override]
   public function start()
   {
-    if ($this->isRunning()) {
-      return false;
-    }
+    if ($this->isRunning()) return false;
 
     $fifo_file = '/tmp/thread_fifo_'.posix_getpid();
-    posix_mkfifo($fifo_file, 0600);
+    if ( !posix_mkfifo($fifo_file, 0600))
+      throw new RuntimeException("Unable to create fifo $fifo_file");
 
     $starterpid = pcntl_fork();
     if ($starterpid == -1) { // Unable to start Starter-Thread
@@ -20,27 +22,32 @@ abstract class Daemon extends Thread
     } else if ($starterpid != 0) { // Pull Child-PID from Starter-Thread
 
       $fifo = fopen($fifo_file, 'r');
-      $data = fread($fifo, 2);
+      if ($fifo === false)
+        throw new RuntimeException("Unable to open fifo $fifo_file");
+      
+      $data = fgets($fifo);
       fclose($fifo);
       unlink($fifo_file);
 
-      $childpid = ord($data[0]) * 256 + ord($data[1]);
-      if ($childpid === 256*256-1) {
-        return false;
-      }
+      if ($data === false)
+        throw new RuntimeException("Unable to read childpid from fifo $fifo_file");
+
+      $childpid = self::parsePID(json_decode($data, flags: JSON_THROW_ON_ERROR));
+      
+      if ($childpid === -1) return false;
 
       $this->pid = $childpid;
       return true;
     } else { // Execute Starter-Thread
 
       $childpid = pcntl_fork();
-      if ($childpid == -1) { // Unable to start Child-Thread
-        $childpid = 256*256-1;
-      }
-      if ($childpid != 0) { // Push Child-PID from Starter-Thread
-        $data = chr((int)(floor($childpid / 256))).chr($childpid % 256);
+      if ($childpid !== 0) { // Push Child-PID from Starter-Thread
+        $data = json_encode($childpid, JSON_THROW_ON_ERROR);
 
         $fifo = fopen($fifo_file, 'w');
+        if ($fifo === false)
+          throw new RuntimeException("Unable to open fifo $fifo_file");
+        
         fwrite($fifo, $data);
         fclose($fifo);
 
@@ -57,4 +64,9 @@ abstract class Daemon extends Thread
       exit();
     }
   }
+
+  private static function parsePID(mixed $value): int {
+    if (is_int($value)) return $value;
+    throw new RuntimeException("Unable to parse childpid into an int.");
+  }
 }
index 1338a4b051adaaffd54c440108af8824425a6aa0..a8f56d52de7dc598280def6e00d9b69bdbe8d58e 100644 (file)
@@ -2,4 +2,4 @@
 
 namespace Graphit\Concurrent;
 
-class MainThread extends Thread { }
+final class MainThread extends Thread { }
index ba24f10171af995e961aee811488081b51515f3c..265099fa4489ae8540131afe88e7675f76d1ca43 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace Graphit\Concurrent;
 
+/** @api */
 abstract class Service extends Daemon
 {
   /** @var string */
@@ -18,7 +19,7 @@ abstract class Service extends Daemon
     }
   }
 
-  /** */
+  #[\Override]
   public function isRunning()
   {
     if ( !$this->pid){
@@ -35,7 +36,7 @@ abstract class Service extends Daemon
     return $running;
   }
 
-  /** */
+  #[\Override]
   public function stop()
   {
     while ($this->isRunning()) {
@@ -44,7 +45,7 @@ abstract class Service extends Daemon
     }
   }
 
-  /** */
+  #[\Override]
   public function setup()
   {
     parent::setup();
@@ -54,7 +55,7 @@ abstract class Service extends Daemon
     }
   }
 
-  /** */
+  #[\Override]
   public function teardown()
   {
     if ($this->isRunning()) {
index 8db0855c04fa7e8e90f762e02647165f77f56643..c3e3680891849046c2ffaec0082a1d2b264cc3ce 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace Graphit\Concurrent;
 
+/** @api */
 abstract class Thread
 {
   /** @var int|null */
@@ -56,23 +57,11 @@ abstract class Thread
   }
 
   /**
+   * @param mixed $siginfo
    * @return void
    */
   protected function chldHandler($siginfo)
   {
-    if (phpversion() == '8.2.9'){
-      if (is_array($siginfo) && isset($siginfo['pid']) && is_int($siginfo['pid'])) {
-        $childpid = $siginfo['pid'];
-
-        if (isset($this->children[$childpid])) {
-          $child = $this->children[$childpid];
-          $child->isRunning();
-
-          unset($this->children[$childpid]);
-        }
-      }
-    }
-
     while (($childpid = pcntl_waitpid(-1, $status, WNOHANG)) > 0) {
       if (isset($this->children[$childpid])) {
         $child = $this->children[$childpid];
diff --git a/tests/DaemonTest.php b/tests/DaemonTest.php
new file mode 100644 (file)
index 0000000..f04133c
--- /dev/null
@@ -0,0 +1,34 @@
+<?php declare(strict_types=1);
+
+use PHPUnit\Framework\TestCase;
+
+use Graphit\Concurrent\Daemon;
+
+require __DIR__."/../vendor/autoload.php";
+
+final class DaemonTest extends TestCase
+{
+    public function testDaemon(): void
+    {
+        $d = (new class() extends Daemon {
+            public function run() {
+                echo "from daemon: PID ".$this->getPid()."!\n";
+                flush();
+                while ( !$this->isStopped()){
+                    usleep(500000);
+
+                    echo "from daemon: Message!\n";
+                    flush();
+                }
+                echo "from daemon: Stopped!\n";
+            }
+        });
+
+        $this->assertTrue($d->start(), "from main: Unable to start daemon");
+        
+        echo "from main: PID ".$d->getPid()."\n";
+        sleep(2);
+        
+        $d->stop();
+    }
+}