WURFL memory allocation fatal error - php

I was using WURFL just fine, then all of a sudden it's throwing this error:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 65484 bytes) in /var/wwwlibs/vnd/WURFL/lib/CustomDevice.php on line 118
I've found some stuff online about Tera-WURFL, but (afaik) I'm not using that, but just the downloaded version from sourceforge. Someone suggested updating the SimpleXML, but I'm just confused as to why WURFL's going over the top.
My wrapper class is as follows:
<?php
namespace vnd\WURFL;
use \WURFL_Configuration_InMemoryConfig;
use \WURFL_WURFLManagerFactory;
/**
* File: WURFL_bootstrap.php
* Sets up and readies the WURFL library for platform and browser detection.
*/
require_once 'WURFL/lib/Application.php';
// ----- WURFL constants ------ //
define('WURFL_ROOT', dirname(__FILE__).'/');
# Directories
define('WURFL_RESOURCES_DIR', WURFL_ROOT.'resources/');
define('WURFL_PERSISTENCE_DIR', WURFL_RESOURCES_DIR.'storage/persistence');
define('WURFL_CACHE_DIR', WURFL_RESOURCES_DIR.'storage/cache');
class WURFLBootstrap extends WURFL_Configuration_InMemoryConfig {
const WURFL_WATCH_MODE = "performance";
const WURFL_VERSION = '2.3.3';
const WURFL_CACHE_EXP = 36000;
# Our WURFL Manager
private $_manager;
# Our device where the capabilities lie
private $_device;
public function __construct(){
$zipPath = $this->getPath();
if(!is_file($zipPath))
die($zipPath.' is not a valid file.');
if(!is_dir(WURFL_PERSISTENCE_DIR) || !is_dir(WURFL_CACHE_DIR))
die(WURFL_PERSISTENCE_DIR.' or '.WURFL_CACHE_DIR.' are not valid directories.');
$this->wurflFile($zipPath);
$this->matchMode(self::WURFL_WATCH_MODE);
$this->persistence('file', array('dir' => WURFL_PERSISTENCE_DIR));
$this->cache('file', array('dir' => WURFL_CACHE_DIR, 'expiration' => self::WURFL_CACHE_EXP));
// Automatically reload the WURFL data if it changes
$this->allowReload(true);
// Create a WURFL Manager Factory from the WURFL Configuration
$wurflManagerFactory = new WURFL_WURFLManagerFactory($this);
// Create our factory and start the process.
$this->_device = $wurflManagerFactory->create()->getDeviceForHttpRequest($_SERVER);
}
/**
* Returns the path to our ZIP file
*/
private function getPath(){
return WURFL_RESOURCES_DIR.'/wurfl-'.self::WURFL_VERSION.'.zip';
}
/**
* Seeing as this is a wrapper class, any calls to our $wflManager (or whatever
* we happened to be assigned to) should be passed on to the actual
* manager object where all the goodies lie.
*
*/
public function __call($name, $arguments){
//return $this->device->$name($arguments);
}
public function getDevice(){
return $this->_device;
}
}
The computer this is running on is an old laptop, so it's not stocked on memory, but what gives? I removed everything that could be causing an over-allocation of memory, but so far it seems like WURFL just doesn't want to run.
I also tried clearing my cache and persistence directories and running it again, but no dice.
One thing I'm thinking is to use the XML configuration class as opposed to the WURFL_Configuration_InMemoryConfig (based on the name I assume it's storing everything in memory, at least temporarily, hence the crash), but I'm curious why it's all of a sudden throwing this error.

I'm not familiar with that library, but in general, you can find out exactly where things go wrong by registering a shutdown function and printing the last error there.
Add the following piece of code somewhere at the start of your script (i.e. before the error occurs):
function my_shutdown_function() {
echo "SHUTDOWN!\n";
$err = error_get_last();
if($err) {
print_r($err);
// optionally, if you want a stack trace:
$ex = new Exception;
print_r($ex->getTraceAsString());
}
}
register_shutdown_function('my_shutdown_function');
You can have similar fun with set_error_handler and set_exception_handler if you like, although both of these will never catch a fatal error (among other failures).

Related

Can Monolog be used on GAE and have the logging levels recorded in Stack Driver?

There are a number of posts on the internet that indicate the right way to use Monolog on the google app engine (GAE standard) is like so:
$logger = new Monolog\Logger($name);
$syslogHandler = new \Monolog\Handler\SyslogHandler("Ident_String", LOG_USER, \Monolog\Logger::INFO);
$syslogHandler->setFormatter(new \Monolog\Formatter\JsonFormatter());
$logger->pushHandler($syslogHandler);
break;
$logger->warn("Starting priam import." );
That does get me logging, but the level is buried in the textPayload:
textPayload: "[28-Feb-2020 11:00:07] WARNING: [pool app] child 22
said into stderr: "[2020-02-28 06:00:07] match_old.INFO: Doing a super
huge SELECT to get all intls. [] []""
and the level icon is always a stippled out asterisk.
Has something changed? I'm using the php 7.3 run-time on GAE standard. Is there a way to use Monolog on GAE that let's you take proper use of stack driver?
There is a package available that allows you to push Monolog to Stackdriver.
As per the doc:
The supplied StackdriverHandler copies the given log level into the
Stackdriver's severity based on your log method.
It also respects the context argument which allows you to send extra
contextual data with your log message. This will be stored in the log
message under jsonPayload.data.
The source code can be found here monolog-stackdriver
I wound up conditionally loading a different logger locally than I do on GAE. It's workable, but it seems like an unnecessary hack considering monolog is such a popular library. And, oh, it's 2020.
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use Google\Cloud\Logging\LoggingClient;
function get_logger($name) {
$kind = getenv('LOG_TYPE')?:'remote';
return _get_logger($kind, $name);
}
function _get_logger($kind, $name) {
if ($kind ==='local') {
$logger = new Monolog\Logger($name);
$logger->pushHandler(new Monolog\Handler\StreamHandler('php://stdout', Monolog\Logger::INFO));
return $logger;
}
$logging = new LoggingClient();
$logger = $logging->psrLogger($name);
return $logger;
}
I'm hoping someone can make this work with monolog.

Why am I unable to catch the Unexpected Alert Exception?

I am using a try catch block to catch an exception and I am unable to catch it as it still says:
In Exception.php line 155:
unexpected alert open: {Alert text : The form is not complete and has not been submitted yet. There is 1 problem with your submission.}
(Session info: chrome=73.0.3683.75)
(Driver info: chromedriver=2.41.578700 (2f1ed5f9343c13f73144538f15c00b370eda6706),platform=Linux 4.15.0-38-generic x86_64)
My feature file:
<?php
use Behat\Behat\Hook\Scope\AfterStepScope;
use Behat\Behat\Tester\Exception\PendingException;
use Behat\Behat\Context\Context;
use Behat\MinkExtension\Context\MinkContext;
use WebDriver\Exception\UnexpectedAlertOpen;
/**
* Defines application features from the specific context.
*/
class FeatureContext extends MinkContext implements Context
{
/**
* Initializes context.
*
* Every scenario gets its own context instance.
* You can also pass arbitrary arguments to the
* context constructor through behat.yml.
*/
public function __construct()
{
}
/**
* #Given I fill in the email field with :email
*/
public function iFillInTheEmailFieldWith($email)
{
dump($email);
$this->visit('/471w2222');
$page = $this->getSession()->getPage();
$page->find('xpath', '//*[#id="tfa_1111"]')->setValue($email);
}
/**
* #When I submit the form
*/
public function iSubmitTheForm()
{
try {
$page = $this->getSession()->getPage();
$page->find('xpath', '//*[#id="submit_button"]')->click();
}
catch (UnexpectedAlertOpen $e){
dd($e->getMessage());
$this->getSession()->getDriver()->getWebDriverSession()->accept_alert();
}
}
}
The alert shows up :
$page->find('xpath', '//*[#id="submit_button"]')->click();
executes. But it is unable to catch it. Why?
As per the error message...
(Session info: chrome=73.0.3683.75)
(Driver info: chromedriver=2.41.578700 (2f1ed5f9343c13f73144538f15c00b370eda6706),platform=Linux 4.15.0-38-generic x86_64)
...the main issue is the incompatibility between the version of the binaries you are using as follows:
You are using chromedriver=2.41
Release Notes of chromedriver=2.41 clearly mentions the following :
Supports Chrome v67-69
You are using chrome=73.0
Release Notes of ChromeDriver v2.46 clearly mentions the following :
Supports Chrome v71-73
So there is a clear mismatch between the ChromeDriver v2.41 and the Chrome Browser v73.0
Solution
Upgrade ChromeDriver to current ChromeDriver v2.46 level.
Keep Chrome version between Chrome v73 levels. (as per ChromeDriver v2.45 release notes)
Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.
If your base Web Client version is too old, then uninstall it and install a recent GA and released version of Web Client.
Take a System Reboot.
Execute your #Test.
Always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully.

Less PHP is broken?

So I am using Less PHP to compile .less files down to .css and I decided to try out a small class I wrote where I take all the .less files in a directory and compile them to .css and move them to their own css directory.
So to test this I took all of twitter bootstrap less and placed it into a directory and then ran my class I wrote, see below, and found less php to be exploding: the current error is:
Error occurred:exception 'Exception' with message 'variable #alert-padding is undefined: failed at 'padding: #alert-padding;'
The class I wrote is just a simple wrapper:
class AisisLess_Less_Less{
protected $_less = null;
protected $_file = null;
public function __construct(){
$this->_file = new AisisCore_FileHandling_File();
$this->_less = new lessc();
$this->init();
}
public function init(){}
public function compile_directory($pattern, $compile_to_dir){
$less_files = $this->_file->get_directory_of_files($pattern);
$this->_compile($less_files, $compile_to_dir);
}
protected function _compile($array_of_files, $compile_directory){
foreach($array_of_files as $file){
$file_without_path = substr( $file, strrpos( $file, '/' )+1 );
try{
$css_file = preg_replace('"\.less"', '.css', $file_without_path);
$this->_less->checkedCompile($file, $compile_directory . $css_file);
}catch(exception $e){
throw new AisisLess_Exceptions_LessException('Error occurred:' . $e);
}
}
}
}
The concept is you use as such:
$less = new AisisLess_Less_Less();
$less->compile_directory(path/to/less/*.less, path/to/compiled/out/put);
My code is just a simple wrapper. The actual error is being thrown by the less library on some variable thing which is apart of the bootstrap less files.
So is the library acting up or is bootstrap failing at coding or have I screwed something up?
And if so how do I fix this?
What I suspect (no proof). If I understand you correctly, you just have the directory of bootstrap files and your code runs through them sequentially compiling them to css. That means the first file it is trying to compile is alerts.less which, low and behold, the very first variable reference in that file is (as of this writing) on line 10:
padding: #alert-padding;
This matches your error.
The issue is most likely that the bootstrap files are not designed to just be blindly compiled, because in most cases each is its own little piece, but requires other key pieces to compile (like variables.less and mixins.less). This is why, generally speaking, you only compile the bootstrap.less file which then will #import all the necessary files.
Basically, if I understand correctly what you have designed and how it works, you picked a bad set of files to run tests on because they are not designed to work that way. Better to just create a few small less files that are independent of each other for testing. However, what this has revealed is that your plan has a potential flaw, in that it will only function on standalone files, so you cannot blindly run any .less file through it, or you will get such compile errors because of broken dependencies.

SOAP Client Error: "Error Fetching Http Headers"

I am trying to use a SOAP Client-Server in my computer and it doesn't look like it is going to work, I am getting this error Error Fetching Http Headers when I try to run my SOAP Client.
I have been looking and the solution that I have encountred is to increase the default_socket_timeout from 60 to 120 seconds and it doesn't work for me, also I have seen another solution that is putting the vhost in my apache KeepAlive Off and that didn't work.
The WSDL is working fine because I try to use it in another computer and it work.
I am running PHP Version 5.3.5-1ubuntu7.4 in Linux Mint using Zend Framework, I hope some of you can help me fix this thank you.
I'm sorry but I don't know what you are using to set up your SOAP service.....
If you can give more information about your SOAP service (poss Zend_Soap given the Zend Framework tag) etc that would be great.
Also, as a quick alternative, you say you've looked at the WSDL on another computer, perhaps try the application in an alternative environment to ensure it's not an environment issue.
May be a simple issue with your client-server code.
UPDATE: Ok so I realised the example I mentioned yesterday wasn't fully implemented so I've hacked something together quickly that you can try to see if it works in your environment.
The code is a mix of something I found here (an example of Zend_Soap_Server) and something from another SO question here (an example of a basic SOAP service test).
I've tested it at my end using ZF 1.11 and the example I'm outlining uses the default Application path you get with a new ZF project (e.g models are in directory application/models so the model shown is headed up Application_Model_Classname).
If it works, you can tweak accordingly....if it doesn't work we can try something else.
Start by creating a new SOAP controller and set the class up like this:
<?php
class SoapController extends Zend_Controller_Action
{
public function init()
{
ini_set("soap.wsdl_cache_enabled", "0"); //disable WSDL caching
$this->_helper->layout()->disableLayout(); //disable the layout
$this->_helper->viewRenderer->setNoRender(); //disable the view
}
public function indexAction ()
{
if (isset($_GET['wsdl'])) {
//return the WSDL
$this->handleWSDL();
} else {
//handle SOAP request
$this->handleSOAP();
}
}
private function handleWSDL ()
{
$strategy = new Zend_Soap_Wsdl_Strategy_AnyType();
$autodiscover = new Zend_Soap_AutoDiscover();
$autodiscover->setComplexTypeStrategy($strategy);
$autodiscover->setClass('Application_Model_SoapService');
$autodiscover->handle();
}
private function handleSOAP ()
{
$server = new Zend_Soap_Server(null,
array('uri' => "http://YOURDOMAIN/soap?wsdl"));
$server->setClass("Application_Model_SoapService");
$server->handle();
}
public function testAction()
{
$client = new Zend_Soap_Client("http://YOURDOMAIN/soap?wsdl");
try {
echo $client->testMethod('test');
} catch (Exception $e) {
echo $e;
}
}
}
In the class above, the WSDL is automatically generated using Zend_Soap_Autodiscover with a SoapService.php file at application/models/SoapService.php used as the template. Note the DocBock comments above each method in your target class are integral to this process.
Next create the SoapService.php file in the default models folder:
<?php
class Application_Model_SoapService
{
/**
* testMethod
*
* #param string $string
* #return string $testSuccess
*/
public function testMethod(string $string)
{
$testSuccess = 'Test successful, the message was: ' . $string;
return $testSuccess;
}
}
If all is working as it should be you can visit:
http://YOURDOMAIN/soap?wsdl
to see the WSDL and visit:
http://YOURDOMAIN/soap/test
to get a success message with the string you specified in the client request within the testAction() code in the SoapController class as part of the message.
Let me know if it's working or not and we can go from there.
I'll be able to have another look on Monday.

Trouble executing the Yii web service demo

I'm fairly new to Yii and am currently trying to use this framework to create some PHP web services. While trying to execute the brief tutorial on web services provided on the Yii web site http://www.yiiframework.com/doc/guide/1.1/en/topics.webservice#declaring-web-service-action I ran into some trouble. Namely, I get a "Maximum execution time of 60 seconds exceeded" fatal error when executing the script. My guess is that the getPrice() method actually never gets called.
I'd appreciate any suggestions related to why this may be happening. The contents of my index.php file are listed below. (Note that the Yii gramework is properly installed and I'm running PHP 5.3.0 with the php_soap extension).
<?php
$yii=dirname(__FILE__).'/../yii/framework/yii.php';
defined('YII_DEBUG') or define('YII_DEBUG',true);
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);
require_once($yii);
class StockController extends CController{
function __construct(){
parent::__construct($this->id, $this->module);
}
public function actions(){
return array(
'quote'=>array(
'class'=>'CWebServiceAction',
),
);
}
/**
* #param string the symbol of the stock
* #return float the stock price
* #soap
*/
public function getPrice($symbol){
$prices=array('IBM'=>100, 'GOOGLE'=>350);
return isset($prices[$symbol])?$prices[$symbol]:0;
//...return stock price for $symbol
}
}
$client=new SoapClient('http://localhost/SampleWebService/?r=stock/quote');
echo $client->getPrice('GOOGLE');
?>
It seems strange that you are declaring the call in the index.php entry script... I'm also not sure why you are overriding the constructor?
And I think, if this really in your entry script, you are missing call the create the application, either Yii::createWebApplication($config)->run(); or Yii::createConsoleApplication($config)->run();, depending on if you are running this as a web or console application.
Have you made sure that the application is running as expected without the SOAP/services stuff? I would set up a basic Hello World app (web or console), then try the web services.

Categories