POE::Component::Client::TCP recklessly removing aliases?
POE::Component::Client::TCP can take an Alias parameter and it will set this alias onto the session on startup of the Session. It does not set the alias on reconnect. However, whenever the shutdown state is entered (e.g. connection dies), it removes the alias. Which means you have to manually manage the alias yourself. If you just use one of the quoted examples and schedule a reconnect event, you'll end up later on with a connected socket but without the alias. Either this makes the Alias parameter pointless, or I'm missing something. Anyone care to enlighten me? Nick
Re: POE::Session-call()
Scott wrote: [...] If you're really only storing data, you really should use an object OR package in the ways I mentioned above. Atleast, if you have any desire to maintain efficiency. Now here I must note, that I didn't come up with the idea of removing inter-session calling all together. I found the idea on the wiki. Now I'm not gonna name names, and I'm not gonna drag others in, because I am a proponent of the idea. I think inter-session calling breaks POE Design patterns. Forcing inter-session communication to be done via post()ing helps force people using the POE Framework to let POE do its thing, and stops people from doing things like creating sessions just for the sake of creating sessions. I also have a need for inter-session calling, so I want to add my tuppence into this :-). Hopefully, my description below isn't so abstract to be non-sensical, but will convey why I need it. I have a fairly complex system that runs various background monitoring tasks (using Wheel::Run) and also takes in requests from the network. Each new network request gains its own session for it to process all work. This work may take some time, also creating new Wheel::Runs, etc. The effect of some of the requests needs to change the frequency of the background monitoring that's going on, or needs to change some of the 'global' data that dictates the manner in which the background processing is run. There is no synchronisation/locking of global data, so the only way to do that is to ask the session owner to make the change. When that type of event happens, we need to get a cross-session event to take place. We can't use post() all the time, because sometimes we need to ensure that the change happens before anything else in the queue is fired off, else we get out-of-order processing. It's a rare thing (only need this twice, in a codebase of ~20k lines of perl), but it does happen. I cannot see (within the constraints of our architecture) how I can achieve this without inter-session call functionality. Nick.
Re: POE::Session-call()
Scott wrote: Nick Williams wrote: Scott wrote: [...] If you're really only storing data, you really should use an object OR package in the ways I mentioned above. Atleast, if you have any desire to maintain efficiency. Now here I must note, that I didn't come up with the idea of removing inter-session calling all together. I found the idea on the wiki. Now I'm not gonna name names, and I'm not gonna drag others in, because I am a proponent of the idea. I think inter-session calling breaks POE Design patterns. Forcing inter-session communication to be done via post()ing helps force people using the POE Framework to let POE do its thing, and stops people from doing things like creating sessions just for the sake of creating sessions. I also have a need for inter-session calling, so I want to add my tuppence into this :-). Hopefully, my description below isn't so abstract to be non-sensical, but will convey why I need it. I have a fairly complex system that runs various background monitoring tasks (using Wheel::Run) and also takes in requests from the network. Each new network request gains its own session for it to process all work. This work may take some time, also creating new Wheel::Runs, etc. The effect of some of the requests needs to change the frequency of the background monitoring that's going on, or needs to change some of the 'global' data that dictates the manner in which the background processing is run. There is no synchronisation/locking of global data, so the only way to do that is to ask the session owner to make the change. When that type of event happens, we need to get a cross-session event to take place. We can't use post() all the time, because sometimes we need to ensure that the change happens before anything else in the queue is fired off, else we get out-of-order processing. It's a rare thing (only need this twice, in a codebase of ~20k lines of perl), but it does happen. I cannot see (within the constraints of our architecture) how I can achieve this without inter-session call functionality. Nick. But communication with child processes will never be synchronous, you have too many steps to go through to communicate with child processes (via pipes, or other methods, nothings going to be _RIGHT_NOW_) I suppose the link I seem to be missing is why a subroutine call would not be satisfactory for this. a subroutine call would be in the context of the currently active session, which is a session just there to deal with the current network request and should go away after that. Therefore I don't want to call the 'create-new-probe-which-will-fire-every-60secs' subroutine, because anything it creates would become a child of this current session and any alarms/delays it wants to set, and any events it wants to post to it's parent would go to me (this session) and not to the parent session which is looking after all background monitoring tasks. [...] but then again I'm not even sure I really understand what you're saying. It's hard to describe the system we've built in a small email, so I'm sorry for the confusion. My point is that in the possibly bizarre architecture we've built, we have a need for cross-session calls. Potentially, I could re-architect things to avoid that, however I'm not sure how at the moment (due to lack of locking in the global data) without very severe changes. Purity of design is great, but if it means I have to spend a week re-architecting compared to the current simple architecture can you see where I'm coming from? Pragmatism won in our system (funny that - same reason we're using perl and POE to start with...). - Scott Nick
Re: Proposal: Registered PIDs
Taking Chris' question further... why not implement wait queues (I'm thinking along the lines of NT). Any session could declare it's interest on a waitable object... and anyone with a reference to that object could call wakeup on it. SIGCHLD handling is therefore just a special case of this - you have a handle on the process, register you want to wait on it. When the pid dies, the object referring to that PID could get a wakeup event. If the waitqueue is empty, the process vaporises in a puff of logic. Else the sessions that declared interest get woken. Nick. On Fri, 13 Feb 2004, Chris Fedde wrote: On Fri, 13 Feb 2004 23:31:56 -0500 Rocco Caputo wrote: +-- | Proposal: Registered PIDs. | | Currently SIGCHLD is broadcast to every session that registers a CHLD | signal handler. Quite often, this means every session with child | processes receives signals for every other one. They all must track | their children and filter the incoming signals against theirs. | | A conversation in IRC reminded me about this issue. I suggested the | customary pattern for dealing with broadcast SIGCHLD. | | One of the parameters is the child PID. You can return unless | exists $heap-{mine}{$pid} | | Philip Gwyn and I had just covered the heavyhanded _signal event, | which is in the throes of deprecation. It further occurred to me that | dispatching SIGCHLD to every session with a handler is often useless, | since most of them don't care one whit about any other session's | process IDs. | | Maybe an optimization would be a Kernel registry mapping child PIDs | to sessions. After you fork, you can call $kernel-forked($pid) to | focus that PIDs SIGCHLD on the current session. POE::Wheel::Run | could do it internally. | | Unregistered PIDs would still be broadcast around. And to be fair, | I guess multiple sessions could register interest in a child PID. | For whatever that's worth. | | This would require a new POE::Kernel method. I wish it could be | incorporated into something like sig(CHLD = event), but re- | registering the SIGCHLD handler shouldn't be necessary for every new | process. +-- Is SIGCHLD the only case where additonal context can be used by the Kernel to decide how to dispatch multicast events to sessions? Is there a way to implement this feature so that other signals could take advantage of pushing selection behavior into kernel? --
Re: Shutting down kernel
Rocco Caputo wrote: On Mon, Feb 16, 2004 at 04:58:42PM -0600, Luke A. Kanies wrote: Is there a stop analog to $poe_kernel-run()? Yes. An experimental stop() was introduced in version 0.28. Most cool! I didn't know about this until now - I've just switched over to using it and it works a charm. Nick.
Re: PoCo::IRC, nicks in use, and sessions
In your code snippet, despite what you print out, you're not actually changing $heap-{nick}, so you're reconnecting with the same name as before... Nick. On Sun, 18 Apr 2004, Ciro wrote: Psilon, my modular POE IRC bot, is coming along fairly well. I've run into a bit of a snafu though. If the preset nick is in use, the bot will just hang there in a sort of half-connected state, until the connection times out, and the server gives a 443 Numeric. Theory on this below. I'd originally tried to deal with this situation by changing the nick, then issuing a ghost command to the local nickserv equivalent, but it never triggered the nick change so nothing else happend. Now I am just trying to reconnect with a random number (1-) appended to the nick, a-la AOL. (Code Below) This event is linked to 'on_irc_443', and it's part of it's own module, which includes wrappers for most of the PoCo::IRC commands (thus the $self references in the function calls. The names should be obvious.) I suppose this might be more of a question for IRC hackers than POE hackers, but I figure there has to be SOME crossover because the module exists. :) The crux of the problem seems to be that the IRC server only returns a Numeric Reply if the nick change FAILS (according to RFC 1459). Anyone have any idea how I might work around this so I don't have to drop and re-establish connection? If I can get that working, then I can get the nickserv's 'ghost' command implimented. Thanks! -Ciro #- Begin Code Snippet --- sub irc_433 #nickname in use { #use the serverhost as a session alias. Makes multi-net usage a lot easer #to debug my $self=shift; my $server=shift; my $sess=$self-{KERNEL}-alias_resolve($server); my $heap=$sess-get_heap(); #pull the heap with our settings my $nick=$heap-{nick}; #drop existing connection $self-disconnect($server, : $nick in use.\n); #generate random nick $nick = $nick . int(rand(1))); print Reconnecting with nick: $nick\n; #reconnect $self-{KERNEL}-post( $server, 'connect',{ Nick = $heap-{nick}, Server = $server, Username = $heap-{username}, Ircname = $heap-{realname},} ); }
Re: New PoCo Guidelines
Chris Fedde wrote: On Tue, 10 Aug 2004 07:59:03 -0600 Wiggins d Anconia wrote: +-- | I'll add another. I think at the very least POE (with the 'E') needs to | stay intact. I know the chatting convention has been to use 'PoCo', | but to keep the two related I think the full 'POE' spelling needs to be | included. The 'x' form definitely aligns well with the DBI - DBIx | pre-existing example. +-- Perhaps I'm too sentimental but I prefer names that are pronounceable. PoCo has a high pronounce-ability. As does POE::Co. POEx seems to be just a capitulation to some week previous art. Non-pronounceable? Bah! /njw POEx chris in eye with stick. A pox on you!, he cries. Okay, never mind me. Back to humming quietly to myself in the corner Nick. The most useful of the DBI extensions are not even in the DBIx space. Class::DBI for example. We have an opportunity to avoid doing something that is just mundane. Lets not miss it only to adhere to some perceived convention. -- Chris Fedde
Re: POE::Wheel::Run on Win32, patch attached
On Mon, 11 Apr 2005, Bas Schulte wrote: On maandag, apr 11, 2005, at 16:03 Europe/Amsterdam, Merijn Broeren wrote: My collegue Nick Williams and I had a stab at making POE::Wheel::Run work on Win32. Isn't that like trying to sail the ocean in a bathtub? Yes, but it's so nice to be able to pick up code that was written on unix and for it to 'just work' on NT as well. Which we've got now. Extending your analogy, POE is the GPS system that allows you to know where you're going whether you're sailing a bathtub or a rickety old ship**. Nick. ** analogies comparing ships to versions of *NIX could abound, but I'll stop there. Suffice it to say that I'm using a very nice apple-branded yacht.
Re: POE::Wheel::Run on Win32, patch attached
Arthur Bergman wrote: On 13 Apr 2005, at 11:49, Merijn Broeren wrote: kill 9,$$; :-) Did you fix that then? The perlfork manpage makes it sound like there will be leaks all over the place. Hmmm.. to be honest I haven't actually touched the win32 code at all... What is the specific reason we need to fork() for Wheel::Run? Because code written using current Wheel::Run assumes parallelism. Do you mean 'why aren't we using CreateProcess'? Because it seemed simpler/less-maintenance to keep the code base as similar as possible between the two different architectures. And you need to do most of the strange shenanigans with StdHandles even when using CreateProcess since the modules that exist for win32 don't expose the underlying win32 facility of defining which handles to use in the spawned process. Nick Cheers - CTO @ Fotango Ltd +447834716919 http://www.fotango.com/ - CTO @ Fotango Ltd +447834716919 http://www.fotango.com/ __ This email has been scanned by the MessageLabs Email Security System. For more information please visit http://www.messagelabs.com/email __
Bug in component Client::TCP...
A strange one, so I'd like to solicit some opinions :-). Client::TCP starts up with a 'server' wheel stashed away in the heap as a POE::Wheel::SocketFactory while it's waiting for the connection to occur. Once the connection is successful, it changes it's {server} in the heap to be a POE::Wheel::ReadWrite. This is commented as 'Ok to overwrite like this as of 0.13'. The issue is that these two wheels have very different methods. The documentation says that if you want to send data, you should invoke $heap-{server}-put(). Which works just fine when {server} is the readwrite wheel. However, 'put' is not a method understood by a socketfactory. Why might you be trying to send data when not connected? Well, the issue is that the connection might die/be reset by the app in which case the state engine will probably transition to 'reconnect' which will switch the {server} back into a SocketFactory. There might still be events waiting to fire (e.g. delays) which will with a bit of bad luck end up firing while {server} is a SocketFactory and not the ReadWrite wheel. Now, I could change my code to check the isa() of the server wheel in all the callbacks, but it seems like a bit of a hack that I have to code defensively around the wheel changing underneath me. Is there a better way of doing this?
Re: Client::TCP question
The normal disconnection happens if the server closes the socket without error. So, your server is immediately closing the socket after sending the reply. This means that if you treat that as a failure and try to do the same thing again, you'll get exactly the same behaviour each time. You need to check the protocol for the server. It may not allow for a single session with many requests. Nick. wonton wrote: Hello list, I seem to be having a slight issue with a Client::TCP component and would appreciate any guidance from those more experienced in the whys and hows of POE. In essence I have a very simple app. that connects to another server, send an initialisation packet and then sends a request. If the initialisation is successful, the same packet is echoed back to my app. and then I attempt to send the request. However, after the init. packet is sent (and the response received) I receive this error Client 2 got read error 0 (Normal disconnection). From a bit of googling I have determined that this is not an error as such (informational). Now if I handle the server_error state explicitly with a reconnect, the app loops indefinitely, initialising and then the socket error and then reconnecting and then intialising again etc. Obviously this isn't quite what I had in mind. (Ultimately there will be many more of these messages travelling between my client and the server and they are alway a request/response type setup). Admittedly, I am only a couple of days in to POE and am still coming to terms with the change in perspective required by POE, which begs the question: am I approaching this incorrectly? trying to squeeze a square block into a round hole? ;) or have i just missed something incredibly simple? any help/insight would be greatly appreciated. cameron
memory (session) leaks in perl
So, I've found the reason that recent releases of POE cause me to get memory leaks - I know others have had problems also, so I wanted to get an open discussion of what I'm being bitten by and possible ways to workaround this. It turns out for me that my sessions aren't being garbage collected. In general, my POE system doesn't *require* the _stop event to be processed and so I never noticed this. However, peeking into the system shows a large number of sessions and I can see that none of the _stop events have been called. This is because of the change: 2005-11-07 06:59:07 (r1852) by hachi poe/lib/POE/Resource/Signals.pm M; poe/lib/POE/Resource/Sessions.pm M Change signal watchers so they keep sessions alive. WARNING: This is a major semantics change in POE. It has the potential to make code 'hang' in places where it formerly did not. This change is necessary so sessions expressing an interest in SIG CH?LD do not die prematurely. (There is a planned mandatory warning for reaped children that were not being watched.) This change fixes RT 15215. The problem with this change is that if I set up a signal handler for something innocuous (e.g. to handle DIE, or one of my hand-rolled signals), this means that the session will do everything appropriately except be garbage collected. I think the intention of this change is reasonable, but to make it the default behavior for all possible signals is a bit keen. If I put in place a handler for a signal, it does NOT mean that I want to WAIT for the signal, it usually means that the signal shouldn't even happen, but that I'm putting in place a handler *in-case* it happens. It certainly shouldn't make my session persistent! I'm not sure of the best way of fixing this. Possibly enhancing the API to have an explicity waitforsig() and maybesig()? (That's half tongue-in-cheek, but is actually one of the better solutions). In terms of normal API, a sig handler shouldn't block, so I would expect the sig() behaviour to follow that paradigm... Thoughts, anyone? Nick
Re: memory (session) leaks in perl
On Wed, 2 Aug 2006, Mathieu Longtin wrote: It was my understanding that a session would stay alive as long as it has child sessions. Did that behavior change? No, this is not down to a child session - AFAIK, the behaviour there has not changed. I'm in agreement with Nick here. If a session is stritly waiting for a child session to finish, then have it call waitpid. $_[KERNEL]-wait_for_child($session, state, @args); wait_for_child would add a link back to the current session, the same way set_delay does. The issue is not wait_for_child, it's wait_for_signal (which doesn't exist). The original problem report was that people were confused by setting up a signal handler for UIDESTROY didn't make the session persistent. That is standard signal semantics and the persistence could've easily been changed by using aliases. The new behaviour in POE (as of .3202) is that when placing a signal handler on a session, e.g. $kernel-sig('uidestroy', 'do_something'); that will now increment the reference count of the session and therefore make that session persistent until the signal handler is deleted via something (and note, not within the _stop event, since we don't get that far). Nick. -Mathieu --- Nick Williams [EMAIL PROTECTED] wrote: So, I've found the reason that recent releases of POE cause me to get memory leaks - I know others have had problems also, so I wanted to get an open discussion of what I'm being bitten by and possible ways to workaround this. It turns out for me that my sessions aren't being garbage collected. In general, my POE system doesn't *require* the _stop event to be processed and so I never noticed this. However, peeking into the system shows a large number of sessions and I can see that none of the _stop events have been called. This is because of the change: 2005-11-07 06:59:07 (r1852) by hachi poe/lib/POE/Resource/Signals.pm M; poe/lib/POE/Resource/Sessions.pm M Change signal watchers so they keep sessions alive. WARNING: This is a major semantics change in POE. It has the potential to make code 'hang' in places where it formerly did not. This change is necessary so sessions expressing an interest in SIG CH?LD do not die prematurely. (There is a planned mandatory warning for reaped children that were not being watched.) This change fixes RT 15215. The problem with this change is that if I set up a signal handler for something innocuous (e.g. to handle DIE, or one of my hand-rolled signals), this means that the session will do everything appropriately except be garbage collected. I think the intention of this change is reasonable, but to make it the default behavior for all possible signals is a bit keen. If I put in place a handler for a signal, it does NOT mean that I want to WAIT for the signal, it usually means that the signal shouldn't even happen, but that I'm putting in place a handler *in-case* it happens. It certainly shouldn't make my session persistent! I'm not sure of the best way of fixing this. Possibly enhancing the API to have an explicity waitforsig() and maybesig()? (That's half tongue-in-cheek, but is actually one of the better solutions). In terms of normal API, a sig handler shouldn't block, so I would expect the sig() behaviour to follow that paradigm... Thoughts, anyone? Nick __ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Re: memory (session) leaks in perl
There appears to be a lack of opinion on this issue. Would it be therefore reasonable to backout the signal change in POE? Or can anyone suggest a way around the problem? Nick. [EMAIL PROTECTED] wrote: On Wed, 2 Aug 2006, Mathieu Longtin wrote: It was my understanding that a session would stay alive as long as it has child sessions. Did that behavior change? No, this is not down to a child session - AFAIK, the behaviour there has not changed. I'm in agreement with Nick here. If a session is stritly waiting for a child session to finish, then have it call waitpid. $_[KERNEL]-wait_for_child($session, state, @args); wait_for_child would add a link back to the current session, the same way set_delay does. The issue is not wait_for_child, it's wait_for_signal (which doesn't exist). The original problem report was that people were confused by setting up a signal handler for UIDESTROY didn't make the session persistent. That is standard signal semantics and the persistence could've easily been changed by using aliases. The new behaviour in POE (as of .3202) is that when placing a signal handler on a session, e.g. $kernel-sig('uidestroy', 'do_something'); that will now increment the reference count of the session and therefore make that session persistent until the signal handler is deleted via something (and note, not within the _stop event, since we don't get that far). Nick. -Mathieu --- Nick Williams [EMAIL PROTECTED] wrote: So, I've found the reason that recent releases of POE cause me to get memory leaks - I know others have had problems also, so I wanted to get an open discussion of what I'm being bitten by and possible ways to workaround this. It turns out for me that my sessions aren't being garbage collected. In general, my POE system doesn't *require* the _stop event to be processed and so I never noticed this. However, peeking into the system shows a large number of sessions and I can see that none of the _stop events have been called. This is because of the change: 2005-11-07 06:59:07 (r1852) by hachi poe/lib/POE/Resource/Signals.pm M; poe/lib/POE/Resource/Sessions.pm M Change signal watchers so they keep sessions alive. WARNING: This is a major semantics change in POE. It has the potential to make code 'hang' in places where it formerly did not. This change is necessary so sessions expressing an interest in SIG CH?LD do not die prematurely. (There is a planned mandatory warning for reaped children that were not being watched.) This change fixes RT 15215. The problem with this change is that if I set up a signal handler for something innocuous (e.g. to handle DIE, or one of my hand-rolled signals), this means that the session will do everything appropriately except be garbage collected. I think the intention of this change is reasonable, but to make it the default behavior for all possible signals is a bit keen. If I put in place a handler for a signal, it does NOT mean that I want to WAIT for the signal, it usually means that the signal shouldn't even happen, but that I'm putting in place a handler *in-case* it happens. It certainly shouldn't make my session persistent! I'm not sure of the best way of fixing this. Possibly enhancing the API to have an explicity waitforsig() and maybesig()? (That's half tongue-in-cheek, but is actually one of the better solutions). In terms of normal API, a sig handler shouldn't block, so I would expect the sig() behaviour to follow that paradigm... Thoughts, anyone? Nick __ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Re: memory (session) leaks in perl
Rocco Caputo wrote: Do you have a use case where it's impossible to do something under the new behavior? I'm working under the assumption that a session can always find a way to call sig(YOUR_SIGNAL_HERE = undef) when it's ready to be destroyed. When it's ready to be destroyed is the key. The new behaviour means that sessions need to track that themselves and (in effect) manage their own reference counting independent of POE's. Before, they could just rely on POE to let them know via _stop. Now, _stop is no longer called unless the session clears the sig first. This is just a catch-22. And it leaves a race condition whereby the session exists but has declared it no longer wants the signal. To be fair regarding discussions on this list, Jonathan Steinert announced the intent to make sig() hold sessions alive in his 19 October 2005 message titled Nastiness, and wrapping up signal reforms. I replied that day with: Big change. I don't mind this; the old semantics of not holding a reference count were tied to _signal, which delivered signals without sessions explicitly asking for them. _signal is gone now, so we can tie the explicit interest of sig() into a reference count to keep the session alive. Nobody else responded. 17 days later I replied with a public go- ahead to make the change. Yes, I realise that there was this discussion previously. However, speaking purely for myself, I didn't understand the impact of this at the time, since I wasn't cognizant of the internals of session reference counting at the time. Now I've looked at this, and I can't see how the new implementation makes sense. My issue is that that the bugzilla that Jonathan was attempting to fix is just trivial to fix using existing POE mechanisms of aliases, since there's an easy point at which you know you want to start the persistence of the session, and there's a well-defined point at which you can release the persistence. However, by making the behaviour of persistence implicit within signals, there is simply no way to achieve the opposite effect (automatic garbage collection). The user (the application) must decide at which point it has no more work to do and at that point it can then clear the signal. And only then will POE do it's garbage collection and call back to the application. This just doesn't make sense. Especially when you compare signals in POE with signals in other dispatchers. Having a handler configured for a signal should not make that process persistent. Maybe I'm thinking about it wrong. To me, explicit interest of sig() does not mean to me that I (this session) want to stay around until that sig, it means to me that it's merely putting in place a handler IN CASE of that sig. It's a really really important distinction. With the huge differentiator that the latter behaviour of 'in-case-of-handlers' CANNOT be achieved in the new POE signal world without careful application coding and ignoring any of the benefits of POE's internal garbage collection. As a compromise, I've also proposed implicitly that maybe we should have a new function wait_for_sig() as well as just sig(), so that we can make the difference in semantics explicit to users. I don't mind which way around the functions and semantics are achieved, so long as there is a way of doing this. Nick
Re: memory (session) leaks in perl
Firstly, thanks for the in-depth reply! Some thoughts interleaved below... Rocco Caputo wrote: On Aug 22, 2006, at 14:06, Nick Williams wrote: Rocco Caputo wrote: Do you have a use case where it's impossible to do something under the new behavior? I'm working under the assumption that a session can always find a way to call sig(YOUR_SIGNAL_HERE = undef) when it's ready to be destroyed. When it's ready to be destroyed is the key. The new behaviour means that sessions need to track that themselves and (in effect) manage their own reference counting independent of POE's. Before, they could just rely on POE to let them know via _stop. Now, _stop is no longer called unless the session clears the sig first. This is just a catch-22. And it leaves a race condition whereby the session exists but has declared it no longer wants the signal. Sessions already do need to manage their reference counts, at least in the sense that they won't exit until they stop watching for events. Signal events are just another kind of event, and the semantics were a bit exceptional for some good reasons that don't necessarily apply anymore. If I understand the catch-22 correctly, it's that a session can't clear its signal watchers from _stop because those watchers prevent _stop from executing. If that's the case, I'd like to point out that it's not very useful to clear any resources from _stop to begin with. POE will automatically reclaim its resources from the session after _stop returns, so any explicit POE cleanup in _stop is an expensive no-op. In my existing code, I'm not cleaning up POE resources - it's *my* resources I'm cleaning up in _stop. The point is that _stop no longer gets called because of the signal handlers, so I can no longer use _stop as a garbage cleanup mechanism similar to DESTROY, since I will by definition always have to know when the session is going to be destructed (in order to remove signal handlers) and therefore _stop becomes superfluous. To be fair regarding discussions on this list, Jonathan Steinert announced the intent to make sig() hold sessions alive in his 19 October 2005 message titled Nastiness, and wrapping up signal reforms. I replied that day with: Big change. I don't mind this; the old semantics of not holding a reference count were tied to _signal, which delivered signals without sessions explicitly asking for them. _signal is gone now, so we can tie the explicit interest of sig() into a reference count to keep the session alive. Nobody else responded. 17 days later I replied with a public go- ahead to make the change. Yes, I realise that there was this discussion previously. However, speaking purely for myself, I didn't understand the impact of this at the time, since I wasn't cognizant of the internals of session reference counting at the time. Now I've looked at this, and I can't see how the new implementation makes sense. I can understand how the implementation might be confusing. The released versions since last December have flaws, especially regarding reference counting. In fact I recently committed fixes for them while portability testing some of Benjamin Smith's new tests. My issue is that that the bugzilla that Jonathan was attempting to fix is just trivial to fix using existing POE mechanisms of aliases, since there's an easy point at which you know you want to start the persistence of the session, and there's a well-defined point at which you can release the persistence. However, by making the behaviour of persistence implicit within signals, there is simply no way to achieve the opposite effect (automatic garbage collection). The user (the application) must decide at which point it has no more work to do and at that point it can then clear the signal. And only then will POE do it's garbage collection and call back to the application. This just doesn't make sense. Especially when you compare signals in POE with signals in other dispatchers. Having a handler configured for a signal should not make that process persistent. The point that persistence shouldn't be tied to signals for flexibility's sake is the start of a slippery slope. What would then stop us from asserting that some timers should not imply persistence? Input timeouts, for example. They don't contribute to a session's lifespan since they're only relevant as long as there's an I/O watcher. Why then should delay() keep sessions alive? We're really talking semantics. A delay says (i.e. is documented as) call me back at time T (in effect). The time will always happen (by definition). So, it makes sense with those semantics that the session should stay alive until at least time T. However a signal (by definition) might never happen. One solution might be to expand the Kernel's APIs for different semantic variants of each watcher
Re: signal design discussions from IRC, leading up to 0.33's change of sig() persistence
Rocco Caputo wrote: Attached as a gzipped text file. Sorry for posting a binary, but I couldn't pass up the 3:1 compression. Please quote relevant parts of the discussion if you want to comment on things. Total time to cull and clean this, about 90 minutes. I hope it explains the motivations and reasoning behind the sig() semantics change. Armed with the full context, we might be able to come up with a better and lasting resolution to the signals problems. Regarding SIGCHLD, I think Philip Gwyn later suggested some form of process ID watcher to supplant the signal. I don't think he proposed it on the list, though. Gosh, thanks for spending that time and providing the discussion, it's quite a fair amount of reading and most valuable :-). To my mind, the initial part of the discussion regarding SIGCHLD is completely orthogonal to the later problem discussed of reference counts. I'm fine with the way that the SIGHCHLD discussion turned out (and btw, in case anyone cares, I'm one of those people that was bitten by system() and qx() going wrong when using POE - the reason being that I don't just use POE, I sometimes (shock horror) use OTHER perl modules too. One doesn't always have control of what those other modules might be doing in their depths and system() is one of those things...) :-). We have some systems written with POE that use over 200 different modules. Tracking downstream modules for their use of system() is just not feasible. So, the SIGCHLD part good. Now let's move onto the reference counting. The discussion implies that the reference counting is neccessary for the SIGCHILD reform. Now that's the bit that's confusing me. 10:13 @ hachi : shouldn't a signal handler keep any session alive, no matter what? 10:44 @ dngor : Signal handlers don't affect reference counts. 11:01 @ hachi : now that has me puzzled 11:02 @ hachi : signal handlers are IPC, like filehandles... why don't they keep sessions alive? That's a misnomer. A handler isn't an IPC like a filehandle. As has been said previously, if you look at UNIX semantics, signals are very very different. And BTW, the ultimate example of this is the DIE handler. If I put in place a DIE handler, it's because of defensive programming (all those external 200 modules :-): I do not EXPECT nor WANT a DIE to actually happen. However, if I put in place a DIE handler, my session becomes persistent. And there's a possible race condition with me removing the DIE handler when I *think* my session is going to die (but hasn't yet reached _stop, and so could quite easily still get a DIE) and the session really evaporating. 11:05 @ dngor : Requiring interest in a signal to be registered explicitly is a relatively new advancement. Now that we have it, I don't see why not. 11:25 @ hachi : well, I think it might have to happen, at least in the case of a CHLD handler, because you can't have that signal watcher dying off silently on people So, that last comment is one of the spurs for putting in reference counting. I've been misled by reading the RT stuff saying that the refcounting was there for the UI_DESTROY problem. Okay. So I *guess* that the signal watcher logic is only invoked if there's someone interested in SIGCHLD. If there's nobody interested in SIGCHLD, then the default behaviour can work just fine. Is that true? And then the follow-on is that if someone was previously interested in SIGHCHLD and then they say they're not, what happens? If the signal handler reverts back to normal perl semantics, then I don't see a problem with the signal watcher no longer spinning. So, I can't quite see how this adds up to requiring persistent sessions. I feel very much that I'm missing some understanding here of how the SIGCHLD stuff has been done. I'll go away and read code while waiting for others to correct me :-) Nick
Re: Component::Client::TCP and a flurry of short messages
lanas wrote: Folks, Using POE::Component::Client::TCP, I want to send several short messages to a server. The server expects each message as a stand-alone message so that it knows that the first byte is a command, the second 4 four bytes a data length, etc... But when I send 4 short messages one right after the other, the 2nd, 3rd and 4th gets bundled 'automagically' into one TCP transmission, and this messes the server. I do not want to touch the server, which I haven't written anyways. So here's how I send the short messages: $_[HEAP]-{server}-put($test1) $_[HEAP]-{server}-put($test2) $_[HEAP]-{server}-put($test3) $_[HEAP]-{server}-put($test4) Is there a way to make certain that each of these messages gets sent on its own in a separate TCP transmission and this, without introducing any delay ? You probably want to look into disabling the Nagle algorithm on your socket. Basically this means setsockopt(TCP_NODELAY) on the socket. Within POE::Component::Client::TCP, you can get the socket handle within the Connected event and set the option there. Nick. If I put a delay between eahc message then each gets sent separately. If I loop around ServerFlushed, sending a message each time ServerFlushed is call, would I get the desired result ? I tried in another setting with ClientFlushed (Component::Server::TCP) and it still bundled the messages together in one transmission. Any help/ideas/suggestions very much appreciated, thanks ! Al Folks, Using POE::Component::Client::TCP, I want to send several short messages to a server. The server expects each message as a stand-alone message so that it knows that the first byte is a command, the second 4 four bytes a data length, etc... But when I send 4 short messages one right after the other, the 2nd, 3rd and 4th gets bundled 'automagically' into one TCP transmission, and this messes the server. I do not want to touch the server, which I haven't written anyways. So here's how I send the short messages: $_[HEAP]-{server}-put($test1) $_[HEAP]-{server}-put($test2) $_[HEAP]-{server}-put($test3) $_[HEAP]-{server}-put($test4) Is there a way to make certain that each of these messages gets sent on its own in a separate TCP transmission and this, without introducing any delay ? If I put a delay between eahc message then each gets sent separately. If I loop around ServerFlushed, sending a message each time ServerFlushed is call, would I get the desired result ? I tried in another setting with ClientFlushed (Component::Server::TCP) and it still bundled the messages together in one transmission. Any help very much appreciated, thanks ! Al
Re: Brace yourself. POE 0.38 is uploaded to PAUSE.
I now have a new problem (don't I always ;-). ReadLine has a modification that I didn't spot earlier (due to our inability to use the last few releases) that doesn't make sense to me. The change labelled r2098 (which went into 0.37, I believe) does this: 2006-09-05 01:41:11 (r2098) by rcaputo; poe/lib/POE/Wheel/ReadLine.pm M A cheezy hack to avoid destroying Wheel::ReadLine instances from within POE::Kernel's space. A proper fix would be to somehow break this wheel's circular references to $self so that DESTROY is triggered immediately when the user destroys the objects' last references. I really really don't understand this. The hack is within DESTROY (i.e. it's within the code that's called when the wheel is evaporating: by definition there are no more references). The hack says if we're evaporating and our parent session has already left the building, then we will not do proper DESTROY semantics but will instead return. An important result of this is that we won't bother resetting the terminal mode back to normal. Which means that quite often after using this module, the terminal will be screwed up. This isn't good. A quick hack fix would be to always restore the terminal state before we hit the conditional return. But then it leads me into where I don't understand: why would we not want to do all of the cleanup? Even if the parent is poe_kernel (i.e. our real session parent has already departed), we can still do cleanup. We're in the DESTROY handler! Does it hurt to do any of that cleanup? Is the comment saying something else? I don't understand the reasoning behind this Nick Rocco Caputo wrote: You have a few hours to perhaps a day or two to prepare yourself for the onslaught of goodness encapsulated in this release. Perhaps most significantly, the two changes you've been waiting for all week (if not longer): + The sig() reference count has been removed. There will be much rejoicing, and probably some gnashing of teeth. + sig_child($pid, $event) was introduced. It waits for an explicit process ID. It holds a session reference count. It automatically clears after the specified process has been reaped and the event has been delivered. But that's not all. Other people were busy improving POE while I was distracted by signals fixes. Give a big shout out to: + Apocalypse made alias_resolve() failures non-fatal when certain assertions are enabled. Rob Bloodgood reported this problem, and persisted in making sure it was fixed. + Vanilla Perl test failures were worked around. That distribution is highly experimental. Its developers don't recommend its use. And it isn't bundled with Win32::Console, needed by the Wheel::Run tests. So those tests are skipped if that module isn't installed. + Martijn Van Beers documented some hook methods in POE::Session, improving POE's kwalitee and passing the features on to you! + Matt Sickler applied a doc patch for TRACE_STATISTICS, submitted by Joel Bernsein. And some 0.37 test failures were fixed. And probably other stuff I forgot. That's okay, though. There's a CHANGES file inside the tarball, and it'll be more than happy to explain everything in much greater detail.
Re: POE::Component::Server::TCP bug fixes, possibly incompatible
Regarding the passing of the socket into clientconnected - I've wished for this in the past, in order to be able to modify TCP options on the socket, which didn't seem possible in the past... It would be nice if that was possible to get at this (either via some available API which I just haven't noticed, or if these patches provide it at clientconnected time). Cheers, Nick. On Thu, Jul 16, 2009 at 12:06 PM, Chris 'BinGOs' Williams ch...@bingosnet.co.uk wrote: On Wed, Jul 15, 2009 at 06:59:12PM -0800, Michael Fowler wrote: On Wed, Jul 15, 2009 at 04:08:48AM -0400, Rocco Caputo wrote: For starters, $_[ARG0] isn't guaranteed to contain anything in particular. Well, it's guaranteed to contain whatever was passed as the 'args' argument to the POE::Session constructor, right? When the session is constructed, 'args' is [ $socket, $client_args ]. That 'args' value needs to remain, because the POE::Wheel::ReadWrite constructor needs it. Having ClientConnected then mirror _start in terms of arguments seems reasonable. I think you're almost right. The correct behavior would be for ClientArgs to align with @_[ARG0..$#_]. This still breaks current code, but it's cleaner. Well, I don't mind breaking old code, but I think ARG0 being the socket should be preserved. Reaching into $heap-{client}-get_input_handle seems awkward. Then again, perhaps it's breaking an abstraction to have direct access to the socket outside of POE::Wheel::ReadWrite. The code I have that actually needs it would benefit from the clarity of having the socket passed as ARG0. Whether or not this breaks some possible future change in something... -- Michael Fowler www.shoebox.net First off, thanks for all the patches, I've applied them all apart from this one. And the main reason for that is deciding what is the best course of action. ( I have no vested interest in POE::Component::Server::TCP myself so can have a non-partisan view ). There is a difference between the documented behaviour and the actual behaviour. I, personally, can't see the need to pass the socket object to the ClientConnected handler, and without any evidence whatsoever to substantiate my claim :) I'd suggest that no one actually uses the socket. ClientConnected would be used to send any initial text to the client which one would usually use $_[HEAP]{client} for. Similarly, one might want to find out the TCP connection details, which are again in the heap $_[HEAP]{remote_ip}, etc. My pennyworth. Anyways, I see three options: a). Make the functionality match the documentation; b). Make the documentation match the functionality; c). Do what dngor suggests and flatten ClientArgs, forget the socket and document as such. Cheers, -- Chris Williams aka BinGOs PGP ID 0x4658671F http://www.gumbynet.org.uk ==