Just got PHP pthreads error
pthreads has detected that the multihread could not be started, the system lacks the necessary resources or the system-imposed limit would be exceeded
and
Cannot initialize zend_mm storage [win32]
in my script...
The PHP code looks like this:
class multihread extends Worker {
public $result;
function __construct($e) {
$this->e = $e;
}
public function run() {
$this->result=file($this->e);
}
}
$threads = 15;
do {
for($i=1; $i<=$threads; $i++) {
if(empty($thread[$i])){
$e=generate_e($i);
if($e==false){
echo "Warning: no more job for e. exiting A"; exit;
}
echo "Starting new thread $i \n";
$thread[$i] = new multihread($e);
$thread[$i]->start(PTHREADS_INHERIT_NONE);
}
elseif($thread[$i]->isWorking()===false) {
if($thread[$i]->result===false){
echo "ERROR:Something wrong with thread $i, exit.";
exit;
}
$thread[$i]->shutdown();
$eval=generate_e($i);
if($e==false){
echo "Warning: no more job exiting B"; exit;
}
$thread[$i] = new multihread($e);
$thread[$i]->start(PTHREADS_INHERIT_NONE);
}
}
usleep(100);
}
while(1);
So, script open new thread, start this thread, then close thread with shutdown() and do it in the loop. It's worked like charm, but after 16000+ opened\closed threads got this error. Seems some resources stay locked? How to fix this?
One shall either detach() the thread before it ends, or call join() on it to wait until it ended.
Missing the one or the other leads to the thread's resources not getting freed and though the system runs out of resources, as observed.
Related
I have a php script to pipe through a mail,
class mailTest
{
// (some code here)
private function saveToDb()
{
// (some code here)
$select = $this->pdo->query("SELECT * FROM tbl_reques WHERE terminal_id = $term AND request_status ='' ");
$select = $select->fetchAll();
if (count($select) > 0) {
echo "Call already Exist (DISCARD)";
} else {
$select_tech = $this->pdo->query("SELECT * FROM tbl_email WHERE terminal_id = $term");
$select_tech = $select_tech->fetchAll();
// (some code here)
}
}
private function sendEmail()
{
$this->today = time();
$this->maildate = date("Y-m-d H:i:s", strtotime('-5 minutes', $this->today));
$select = $this->pdo->query("Select * from tbl_reques WHERE maildate >= '$this->maildate' ");
// some code here
mail($this->from_email, $this->subject, $newmsg, $headers);
}
}
The problem is any time the condition is False i.e echo "Call already Exist (DISCARD)"; The code will not go to the Next Function. i.e the program get halt.
PLS is there a way that if that condition is not met, the program will JUMP to next function for continuation of execution. Or is it possible to use GOTO statement.
Pls what is the best way to handle this in PHP.
Thanks
You have a couple option for this. You can return at the point of failure. Which would exit the function at this point and then do whatever is next in the script being ran. Be sure to do the clean up before your return.
if(count($select) > 0) {
echo "Call already Exist (DISCARD)";
//Clean up if needed
return; //You could also return the message
//or an error code and have another
//evaluation based on that.
} else {
// Or passes
}
You could call the next function but this would be a very bad flow in my opinion
if(count($select) > 0) {
echo "Call already Exist (DISCARD)";
//Clean up if needed
$this->sendEmail();
} else {
// Or passes
}
The reason this would be bad is if say in the script you have
$mailTest = new mailTest();
$mailTest->saveToDb();
$mailTest->sendEmail(); //When the above fails this is called twice.
You could likewise throw an exception
if(count($select) > 0) {
echo "Call already Exist (DISCARD)";
throw new Exception("Call already Exist (DISCARD)");
} else {
// Or passes
}
Now you need to use try and catch
$mailTest = new mailTest();
try {
$mailTest->saveToDb();
catch (Exception $e){
//Do something with $e
//Clean up the failure if needed
}
$mailTest->sendEmail();
There is a finally block as well which would run in cases where your catch stops the script.
PHP in fact has a GOTO statement, see http://php.net/manual/de/control-structures.goto.php
However, it is considered bad style to use it, or in the words of #Konamiman
Unless you are programming in assembler, GOTO should always be treated the same way as the life vest of the airplanes: it is good to have them available, but if you need to use them it means that you are in big trouble.
You can call a function simply by writing its name followed by brackets. In the case of class functions you apply it to $this:
$this->sendEmail();
I'm writing a converter that takes a document from database (mongo db), does some magic with its fields and writes it back. Repeat for all relevant docs.
The problem is, after successful processing EntityManager#flush() just silently crashes not committing any changes to db or returning an error code.
I encountered this crash before but I've been able to evade it by reducing quantity of entities to flush(). Now it won't work even with one.
The code goes like this:
public function convertTagsAction() {
$result = [];
$result['docs processed'] = 0;
$result['tags added'] = 0;
$repo = $this->getRepo('Portal');
$cnt = 0;
$dm = $this->getDM();
$docs = $repo->findBy([...]);
$result['docs to process'] = count($docs);
foreach($docs as $doc) {
....//executing just for ONE doc at the moment
$result['docs processed']++;
//file_put_contents('1.txt', print_r($doc, true));
//Everything is ok in the file
$dm->persist($doc);
echo $dm->getUnitOfWork()->size();
// returns 6087 which I deem strange
//this helped me before to manage this problem
$cnt++;
if ($cnt >= 20) {
$dm->flush();
$cnt = 0;
}
}
try {
$dm->flush();
} catch (Exception $e) {
echo $e->getMessage(); //Nah, won't tell me anything
}
return $this->success($result);
}
So now, whenever flush() is called, the script just quits and not even returns any output (should do so in the last line). Any ideas how to solve it?
I recently upgraded from php 5.4.26 to 5.4.28 after the upgrade I am getting this error
Notice: Unknown: send of 6 bytes failed with errno=32 Broken pipe in Unknown on line 0
When ever I run the following code:
<?php
$tasks = array(
'1' => array(),
'2' => array(),
);
ini_set('display_errors', true);
class RedisClass {
private $redis;
public function __construct()
{
$this->redis = new Redis();
$this->redis->connect('localhost', 6379);
}
}
$redis = new RedisClass();
foreach ($tasks as $index => $task)
{
$pid = pcntl_fork();
// This is a child
if($pid == 0)
{
echo "Running ".$index." child in ". getmypid() ."\n";
break;
}
}
switch($pid)
{
case -1 :
die('could not fork');
break;
case 0:
// do the child code
break;
default:
while (pcntl_waitpid(0, $status) != -1)
{
$status = pcntl_wexitstatus($status);
echo "Child completed with status $status\n";
}
echo "Child Done (says: ". getmypid() .")";
exit;
}
If I only fork one child then I do not get the PHP Notice. If I run any more than 1 child I get the PHP Notice for every child except the first child.
Does anyone have any clues as to what is going on here?
I am assuming it is trying to close the Redis connection multiple times but this is code I have been running for at least 4 months with out any issues.
It only starting displaying these notices after the upgrade to 5.4.28.
I have looked at the PHP change logs but I cannot see anything that I think may explain this issue.
Should I report this to PHP as a bug?
UPDATE:
Looks like it "may" be a Redis issue, I am using phpredis I tested the same code with a mysql connection instead of loading Redis and I do not get the error.
class MysqlClass {
private $mysqli;
public function __construct()
{
$this->mysqli = mysqli_init(); //This is not the droid you are looking for
$this->mysqli->real_connect('IP_ADDRESS',
'USER_NAME',
'PASSWORD');
}
}
$mysql = new MysqlClass();
The problem here is that you do not reconnect Redis in the child process. Like Michael had said, you do not have an active connection from the second child onwards. That mysql example should not work if you also make some queries.
I have had the exact problematic behaviour with the "MySQL server has gone away" error and also with Redis.
The solution is to create a new connection to MySQL and to Redis in the child. Make sure if you have a singletone that handles the MySQL/Redis connection to reset the instances ( that was also a problem for me ).
My following method uses an array of data $FDFData to create an FDF file:
public function writeFDFFile($FDFData) {
$fdf_file = time().'.fdf';
$fdf = $this->createFDF(PDF_FORM, $FDFData);
// write the file out
if($fp=fopen($fdf_file,'w')) {
fwrite($fp,$fdf,strlen($fdf));
} else {
throw new Exception('Unable to create file: '.$fdf_file);
}
fclose($fp);
return $fdf_file;
}
One of my scripts runs absolutely fine:
require_once('PDFPrinter.php');
try {
$printer = new PDFPrinter();
$FDFData = $printer->assembleFDFData(9);
$fdf_file = $printer->writeFDFFile($FDFData);
$printer->downloadFile($fdf_file);
}catch(Exception $e) {
echo $e->getMessage();
}
but I can't get my test code to run because I get a:
Unexpected PHP error [fopen(1315558352.fdf) [<a href='function.fopen'>function.fopen</a>]: failed to open stream: Permission denied]
error thrown:
require_once(dirname(__FILE__) . '/simpletest/autorun.php');
require_once(dirname(__FILE__) . '/../PDFPrinter.php');
class PDFPrinterTest extends UnitTestCase {
private $printer;
private $FDFData;
function setUp() {
$this->printer = new PDFPrinter();
$this->FDFData = $this->printer->assembleFDFData(5);
}
function testException() {
try {
$this->printer->writeFDFFile($this->FDFData);
$this-assertTrue(true);
} catch(Exception $e) {
$this->assertTrue(false);
}
}
}
Both scripts are run in directories with the correct permissions. I am running my test scripts through the browser as well, so it's not that I have a different environment.
I'm stuck as to how to proceed to find the issue really.
My directory structure:
HOME - PDFPrinter.php
|
-----tests - PDFPrinterTest.php
|
------simpletest - autorun.php
Any suggestions as to how I could find the issue?
Many thanks
Update
I have tried changing my test class so that the only test function in there is:
function testWrite() {
try {
$name = "testing.txt";
if($fp=fopen($name, 'w')) {
fwrite($fp, "Blah");
} else {
throw new Exception("Nope.");
}
$this->pass("All good");
} catch(Exception $e) {
$this->fail("Not good");
}
}
but the exception is still thrown with the warning.
Yet a very simple script run from the same directory works fine:
$name = "Test.txt";
if($fp=fopen($name, 'w')) {
fwrite($fp, "Working");
} else {
throw new Exception("Nope.");
}
fclose($fp);
that will actually create and write to the file.
Finally found the solution which was that the file name needed to be the full absolute address in order for it to work in both scripts for some reason. This was suggested in one of the answers for this SO question which I quote below:
Use fopen($_SERVER['DOCUMENT_ROOT'].'test.txt','a+');
so for my code, I have used:
if($fp=fopen($_SERVER['DOCUMENT_ROOT'].$name, 'w')) {
fwrite($fp, "Working");
}
In your test
fwrite("Blah");
should be
fwrite($fp, "Blah");
I'm not sure what the problem in the original code is though.
failed to open stream: Permission denied
There is one important programmer's skill every developer ought to master.
Here it is:
To trust your eyes
If your PHP telling you that permission is denied - so it is. Just doble-check it. It is not a big deal yet noone can do it for you.
I was challenged how to break or end execution of a parent function without modifying the code of the parent, using PHP
I cannot figure out any solution, other than die(); in the child, which would end all execution, and so anything after the parent function call would end. Any ideas?
code example:
function victim() {
echo "I should be run";
killer();
echo "I should not";
}
function killer() {
//code to break parent here
}
victim();
echo "This should still run";
function victim() {
echo "I should be run";
killer();
echo "I should not";
}
function killer() {
throw new Exception('Die!');
}
try {
victim();
} catch (Exception $e) {
// note that catch blocks shouldn't be empty :)
}
echo "This should still run";
Note that Exceptions are not going to work in the following scenario:
function victim() {
echo "this runs";
try {
killer();
}
catch(Exception $sudden_death) {
echo "still alive";
}
echo "and this runs just fine, too";
}
function killer() { throw new Exception("This is not going to work!"); }
victim();
You would need something else, the only thing more robust would be something like installing your own error handler, ensure all errors are reported to the error handler and ensure errors are not converted to exceptions; then trigger an error and have your error handler kill the script when done. This way you can execute code outside of the context of killer()/victim() and prevent victim() from completing normally (only if you do kill the script as part of your error handler).