I have been using AnyEvent for a while and EV is installed in my computer.
I have the understanding that if EV is installed AnyEvent will try to use it as first resort, but I keep seeing people doing this:
use EV;
use AnyEvent;
From the documentation:
During the first call of any watcher-creation method, the module tries to detect the currently loaded event loop by probing whether one of the following modules is already loaded: EV, AnyEvent::Loop, Event, Glib, Tk, Event::Lib, Qt, POE. The first one found is used.
This means it will first check if any of these modules are already loaded and then use it. For example if Tk is loaded but EV not it will use Tk like in the following example:
use Some_Module_Which_Implicitly_loads_Tk;
use AnyEvent;
By explicitly loading EV one makes sure that it is available when doing the probing described above and that it is thus used even if other event loop modules are loaded too.
Related
I have a circular dependency problem with Perl modules: say package X uses Y and wants to hold a static reference to an Y instance, and package Y uses X and wants to hold a static reference to an X instance.
Simply saying our $x_instance = new X will give Can't locate object method "new" in the module that was not loaded first.
I figured something like
our $x_instance;
INIT { $x_instance = new X }
would make sense, so I read everything about the specially named blocks.
Well, this works in a simple test I made, but in my real application it systematically shows Too late to run INIT block. The same happens with CHECK blocks.
The only explanation I found was from Perl Monks and I'm afraid I couldn't make much sense of it.
Does someone have an explanation about how Perl goes about executing CHECK and INIT block that goes beyond what is in perlmod, and would help me understand why my blocks and sometimes executed and sometimes not?
By the way, I just want to understand this—I am not specifically asking a solution to my original circular dependency problem, as I have a workaround that I am reasonably happy about:
our $x_instance;
sub get_x_instance {
$x_instance //= new X;
return $x_instance;
}
INIT blocks are executed immediately before the run time phase is started in the order the compiler encountered them during the compilation phase.
If you use use require (or do) at run time to compile a Perl file that includes an INIT block then the block won't be executed.
It is rare that there is a real reason to use require in preference to use.
Despite your confidence, there must be a place where you are attempting to load a module at run time that contains an INIT block. I suggest you install and use Carp::Always so that the Too late to run INIT block message is accompanied by a stack backtrace that will help you find the erroneous call.
As the title says I'm trying to make a perl daemon which, being long-running I want to be sane on resource usage.
All the examples / documentation I've seen doesn't seem to mention a way to disconnect a session.
The best documentation on the topic I can find in WWW::Mechanize::Firefox::Troubleshooting
Where it's suggested the object (and connection?) is kept alive until global destruction.
In short, I've seen no 'disconnect' function, and wonder if I'm missing something.
Disconnection seems to be handled via destructors. Perl uses special DESTROY methods for this. It is not advisable to call this method manually.
You need to decrease the refcount of your $mech object in order to get it destroyed automatically. This happens when the variable drops out of scope, in the Global Destruction Phase at the end of the process, or (in the case of objects), by assigning something different to your variable, e.g.
$mech = undef;
To completely deallocate any variable, you can also
undef $mech; # which btw is the answer provided in the FAQ you linked
The differences are subtle, and irrelevant in this case.
I'm trying to use GStreamer within an existing perl application that uses AnyEvent with the EV event loop. It is not a Glib application. I have loaded EV::Glib to get the Glib main loop to use EV. I freely admit that, with respect to Glib, I am pretty ignorant. I think that I have all the bits that I need but I am struggling (failing) to get them to work together.
If I use a standalone perl program to build a GStreamer pipeline and then put it into PLAYING state then it all simply works. I do not need to do anything with a Glib mainloop or otherwise tickle the GStreamer bus.
Building the same pipeline in my existing application, within the context of an AnyEvent event-handler, then it fails to run the pipeline. I have played around with various ways of trying to exercise it, including calling $pipeline->get_bus->poll(). If I call ...->poll() repeatedly in the original event handler (that is, the handler does not return) then it works but this is clearly not a valid solution. Calling ...->poll() in an AnyEvent timer callback does not run the pipeline.
My best guess at the moment is that EV::Glib enables some level of integration but does not actually run the necessary bits of the main loop. What am I missing?
I came here with a similar question regarding EV::Glib usage, but ended up having no issues using it.. So maybe I'm missing what you're trying to do here.
Here is the simple script I knocked up to test how EV::Glib works:
use EV::Glib;
use Gtk2 '-init';
my $t = EV::timer 1, 1, sub { print "I am here!\n" };
Glib::Timeout->add(1000, sub { print "I am also here!\n" });
my $window = Gtk2::Window->new('toplevel');
$window->signal_connect(delete_event => sub { EV::unloop });
my $button = Gtk2::Button->new('Action');
$button->signal_connect(clicked => sub {
print("Hello Gtk2-EV-Perl\n");
});
$window->add($button);
$window->show_all;
EV::loop;
With this the signal handler on the button will work, and so too will both the timer events. So the EV loop will correctly drive the entire thing.
The main issue I can see is in the documentation: "This [module] makes Glib compatible to EV. Calls into the Glib main loop are more or less equivalent to calls to EV::loop (but not vice versa, you have to use the Glib mainloop functions)."
What this means is if you're hookling up an EV::loop event, it won't equate to a Glib::mainloop and so might not 'tickle' (or 'be tickled by') your GStreamer event. Maybe that could be the issue you're experiencing, especially if you're using AnyEvent and its generic callbacks which are likely translating to EV::loop calls instead of Glib::MainLoop calls.
This is all just a guess though -- I've never used GStreamer myself, and I certainly don't know what you're trying to achieve without seeing more code. But I think my halfassed conclusion is pretty sound advice regardless: If you're using something specific to Glib, you should probably be hooking up events to it using Glib.
EV::Glib embeds Glib into EV - you (and everybody else) has to use EV to make it work. Chances are that gstreamer doesn't know about this and disrespectfully calls glib mainloop functions internally, which doesn't work.
Fortunately there is another module that does just the opposite: Glib::EV. That module makes Glib use EV internally. When using it, you can/should use the glib mainloop functions (you can use EV watchers, but you cannot call glib functions from the EV callbacks, as glib doesn't support that).
It might be better suited to your application, as applications using glib will "just work", as the EV usage is completely internal.
Another possible issue is that perl modules are dynamically linked, and only "accidentally" get the same library. For all of this to work, you need to ensure that all perl modules link against the same shared glib library.
I have very simple constructor and destructor for some C-based library. Well, i need to catch signals like TERM and others to enforce destructor calling on perl's mandatory death with killall perl e.g.
In fact i need local $SIG{TERM} for each object to be installed, written inside XS constructor. Is it possible?
!thanx!
Not exactly. A signal is sent to and trapped by a process, not objects.
Another approach might be to maintain a global list of all the objects that must be cleaned up, and install a single signal handler that will clean up each object on that list.
I'm working in a large Perl application and would like to get stack traces every time 'die' is called. I'm aware of the Carp module, but I would prefer not to search/replace every instance of 'die' with 'confess'. In addition, I would like full stack traces for errors in Perl modules or the Perl interpreter itself, and obviously I can't change those to use Carp.
So, is there a way for me to modify the 'die' function at runtime so that it behaves like 'confess'? Or, is there a Perl interpreter setting that will throw full stack traces from 'die'?
Use Devel::SimpleTrace or Carp::Always and they'll do what you're asking for without any hard work on your part. They have global effect, which means they can easily be added for just one run on the commandline using e.g. -MDevel::SimpleTrace.
What about setting a __DIE__ signal handler? Something like
$SIG{__DIE__} = sub { Carp::confess #_ };
at the top of your script? See perlvar %SIG for more information.
I usually only want to replace the dies in a bit of code, so I localize the __DIE__ handler:
{
use Carp;
local $SIG{__DIE__} = \&Carp::confess;
....
}
As a development tool this can work, but some modules play tricks with this to get their features to work. Those features may break in odd ways when you override the handler they were expecting. It's not a good practice, but it happens sometimes.
The Error module will convert all dies to Error::Simple objects, which contain a full stacktrace (the constructor parses the "at file... line.." text and creates a stack trace). You can use an arbitrary object (generally subclassed from Error::Simple) to handle errors with the $Error::ObjectifyCallback preference.
This is especially handy if you commonly throw around exceptions of other types to signal other events, as then you just add a handler for Error::Simple (or whatever other class you are using for errors) and have it dump its stacktrace or perform specialized logging depending on the type of error.