info(sprintf('%s:+ BBS Server Starting (%d)',self::LOGKEY,getmypid())); $o = Setup::findOrFail(config('app.id')); $start = collect(); if (TRUE || $o->ansitex_active) $start->put('ansitex',[ 'address'=>$o->ansitex_bind, 'port'=>$o->ansitex_port, 'proto'=>SOCK_STREAM, 'class'=>new Ansitex($o), ]); if (TRUE || $o->viewdata_active) $start->put('videotex',[ 'address'=>$o->videotex_bind, 'port'=>$o->videotex_port, 'proto'=>SOCK_STREAM, 'class'=>new Videotex($o), ]); $children = collect(); Log::channel('bbs')->debug(sprintf('%s:# Servers [%d]',self::LOGKEY,$start->count())); if (! $start->count()) { Log::channel('bbs')->alert(sprintf('%s:! No servers configured to start',self::LOGKEY)); return; } //pcntl_signal(SIGCHLD,SIG_IGN); foreach ($start as $item => $config) { Log::channel('bbs')->debug(sprintf('%s:- Starting [%s] (%d)',self::LOGKEY,$item,getmypid())); $pid = pcntl_fork(); if ($pid === -1) die('could not fork'); // We are the child if (! $pid) { Log::channel('bbs')->withContext(['pid'=>getmypid()]); Log::channel('bbs')->info(sprintf('%s:= Started [%s]',self::LOGKEY,$item)); $server = new SocketServer($config['port'],$config['address'],$config['proto']); $server->handler = [$config['class'],'onConnect']; try { $server->listen(); } catch (SocketException $e) { if ($e->getMessage() === 'Can\'t accept connections: "Success"') Log::channel('bbs')->debug(sprintf('%s:! Server Terminated [%s]',self::LOGKEY,$item)); else Log::channel('bbs')->emergency(sprintf('%s:! Uncaught Message: %s',self::LOGKEY,$e->getMessage())); } Log::channel('bbs')->info(sprintf('%s:= Finished: [%s]',self::LOGKEY,$item)); // Child finished we need to get out of this loop. exit; } Log::channel('bbs')->debug(sprintf('%s:- Forked for [%s] (%d)',self::LOGKEY,$item,$pid)); $children->put($pid,$item); } // Wait for children to exit while ($x=$children->count()) { // Wait for children to finish $exited = pcntl_wait($status); if ($exited < 0) abort(500,sprintf('Something strange for status: [%s] (%d)',pcntl_wifsignaled($status) ? pcntl_wtermsig($status) : 'unknown',$exited)); Log::channel('bbs')->info(sprintf('%s:= Exited: #%d [%s]',self::LOGKEY,$x,$children->pull($exited))); } // Done Log::channel('bbs')->debug(sprintf('%s:= Finished.',self::LOGKEY)); } }