On Sat, Dec 5, 2015 at 7:33 AM, Max Leske <maxle...@gmail.com> wrote:
> Good stuff Mariano! I think a similar approach will work for Seaside 2.8. > > Great. > - I think you might want to override #handleException: and inject the > process variable there. Then it doesn’t matter from where the debugger is > being opened and you don’t have to mess with the exception handling logic > (which inevitably leads to trouble in my experience). > Good idea. The reason I was hooking there is because I was setting in the process local variable once I know I was already at the UI Manager process and no the Zinc Server one that was processing the request. However...let me explain... Whenever you evaluate something from the debugger, inspector, etc...all that is being run with UI Manager process. While the stack you debugging was actually created at another process (the Zinc Server one that was processing the request). If we store in PLC (processor local variables) when we are in the Zinc process, then the debugger does not see the values at all (since it is in UIManager). We may be able to fix this, but we will need to hook in every possible "evaluation" done from debugger: inspect, do it, print it, etc etc etc. The only reason it make sense to store the values in PLC of the Zinc process rather than UIManager (and make all necessary hooks in inspect, print, etc) is because that would allow us to debug multiple exceptions at the same time. Right now, since values are stored in PLC of UIManager, those are shared for all debuggers. Meaning...you allow only ONE debugger. The last debugger will set new values and the older debuggers will now get the "new values". You can verify this yourself by opening 2 debuggers from my test case. Anyway.... if we are already going to support 1 one debugger at a time (it's more than enough for my needs), it make no sense to use PLC from UIManager. In fact, the values could be stored ANYWHERE. The only condition is to be able to reach them in each WADynamicVariable subclass >> defaultValue. In my last commit you can see this new approach. For this experiment I store things in Smalltalk globals but next I will: 1) Use a class side variable in WAPharoDebuggererErrorHandler 2) Automatically store all subclasses of WADynamicValue with convetion..say: WADynamicValue allSubclasses do: [:each | WAPharoDebuggererErrorHandler storedDynamicValues at: (each name, 'Value') put: each value ]. and then, each WADynamicValue subclass would need to implement #defaultValue like this: defaultValue " This is an override from SeasidePharoDebugging because before raising a signal we first check if we have the value stored. That way, everywhere we evaluate code in a debugger that end ups doing 'WACurrentRequestContext value' will simply get up to this place. Since in WAPharoDebuggererErrorHandler >> #open: we stored the dynamic variables, we should have the value " ^ (WAPharoDebuggererErrorHandler storedDynamicValues at: (self name, 'Value') ifAbsent: [ WARequestContextNotFound signal ]) ifNil: [ WARequestContextNotFound signal ] Thoughts? > - There’s an “er” too many in WAPharoDebuggererErrorHandler :) > - Your current solution doesn’t work for the UI process. Snippet: > > [ > WACurrentRequestContext > use: 'foo' > during: [ > WAPharoDebuggererErrorHandler new handleExceptionsDuring: [ self halt. ] ] > ] fork. > > Without the #fork the process will be the UI process and the request will > not be saved into the process variable. That’s not a deal breaker but nice > for testing. > > Can you try with the latest version that does not use LPC if it works? > Incidentally, you could reuse WACurrentRequestContext (instead of the new > process variable) in #openDebuggerOn: like so: > > WACurrentRequestContext use: currentRequest during: [ > process > debug: anError signalerContext > title: anError description > full: true. > ] > ]. > > That would make it much easier for users not familiar with the process > variable trick. > > > mmmmm are you sure this works? (in any case, we will not go that path anymore but I am curious if that did work for you) Thanks! > > Cheers, > Max > > > On 05 Dec 2015, at 00:11, Mariano Martinez Peck <marianop...@gmail.com> > wrote: > > I added more tests to WACurrentRequestDebuggingTest. If you see, all tests > work except #callbackAndHalt. > > At a later point we will likely need to do this for the rest of the > WADynamicVariable subclasses (they are 3 in total). > > Cheers, > > On Fri, Dec 4, 2015 at 7:17 PM, Mariano Martinez Peck < > marianop...@gmail.com> wrote: > >> OK, I tested it and it works. I added only one test but I plan to add >> more. >> >> On Fri, Dec 4, 2015 at 4:59 PM, Mariano Martinez Peck < >> marianop...@gmail.com> wrote: >> >>> OK, I started publishing here: >>> http://smalltalkhub.com/mc/marianopeck/MarianoPublic/main package >>> called SeasidePharoDebugging >>> I did not even have the time to try it..just committed. >>> I must leave now. >>> >>> byw >>> >>> On Fri, Dec 4, 2015 at 2:43 PM, Mariano Martinez Peck < >>> marianop...@gmail.com> wrote: >>> >>>> OK, I solved the Halt problem. I did it by adding: >>>> >>>> WADebugErrorHandler class >> exceptionSelector >>>> ^ super exceptionSelector, Halt >>>> >>>> And this override: >>>> >>>> WAErrorHandler >> handleException: anException >>>> (Error handles: anException) >>>> ifTrue: [ ^ self handleError: anException ]. >>>> (Warning handles: anException) >>>> ifTrue: [ ^ self handleWarning: anException ]. >>>> (Halt handles: anException) >>>> ifTrue: [ "Lets debug Halt as an error so that we can take advantage of >>>> the #openDebuggerOn: hook" >>>> ^ self handleError: anException ]. >>>> ^ super handleException: anException >>>> >>>> Can you try that too? >>>> >>>> if it gets complicated to test, I can fire a first version of a package >>>> and publish it in Shub. >>>> >>>> >>>> On Fri, Dec 4, 2015 at 2:12 PM, Mariano Martinez Peck < >>>> marianop...@gmail.com> wrote: >>>> >>>>> >>>>> >>>>> On Fri, Dec 4, 2015 at 1:29 PM, Mariano Martinez Peck < >>>>> marianop...@gmail.com> wrote: >>>>> >>>>>> OK. But be aware it is very very little tested and probably still a >>>>>> hack, and it still need overrides. Hopefully you will help me to polish >>>>>> it >>>>>> until we get a "SeasidePharoDebugging" package with no override :) >>>>>> >>>>>> All what I mention here is tested in Pharo 4.0 with Seaside 3.1.4.1. >>>>>> >>>>>> These are the steps: >>>>>> >>>>>> 1) Create a >>>>>> >>>>>> ProcessLocalVariable subclass: #WACurrentRequestContextPLV >>>>>> instanceVariableNames: '' >>>>>> classVariableNames: '' >>>>>> category: 'SeasidePharoDebugging' >>>>>> >>>>>> 2) Override GRPharoPlatform >> openDebuggerOn (see highlighted >>>>>> lines) >>>>>> The idea is to simply store the WACurrentRequestContext into a >>>>>> processor local variable before we loose it. >>>>>> >>>>>> openDebuggerOn: anError >>>>>> | process currentRequest | >>>>>> process := Processor activeProcess. >>>>>> currentRequest := WACurrentRequestContext value. >>>>>> >>>>>> "If we are running in the UI process, we don't want to suspend the >>>>>> active process. The >>>>>> error was presumably triggered while stepping in the Debugger. If we >>>>>> simply immediately >>>>>> signal an UnhandledError, the debugger will catch this and display >>>>>> the signaling context. >>>>>> It isn't perfect or pretty but it works." >>>>>> (ProcessBrowser isUIProcess: process) >>>>>> ifTrue: [ >>>>>> UnhandledError signalForException: anError ] >>>>>> ifFalse: [ >>>>>> WorldState addDeferredUIMessage: [ >>>>>> WACurrentRequestContextPLV value: currentRequest. >>>>>> process >>>>>> debug: anError signalerContext >>>>>> title: anError description >>>>>> full: true. >>>>>> ]. >>>>>> process suspend ] >>>>>> >>>>>> >>>>>> 3) Override WACurrentRequestContext class >> defaultValue >>>>>> >>>>>> defaultValue >>>>>> ^ WACurrentRequestContextPLV value ifNil: [ WARequestContextNotFound >>>>>> signal ] >>>>>> 4) Set WADebugErrorHandler as the error handler in your seaside app >>>>>> (I am not sure if this step is needed). >>>>>> >>>>>> And that's all. Try to put a "self whateverMethodThatCausesDNU" and >>>>>> then, try to evalaute something from the debugger that calls #session or >>>>>> #requestContext etc... for example, evaluate "WAComponent new session" >>>>>> and >>>>>> that should work: >>>>>> >>>>>> Besides the overrides I still have doubts: >>>>>> >>>>>> a) do we need WADebugErrorHandler ? >>>>>> >>>>> >>>>> Yes, we do, because we are hooking in #openDebuggerOn: and that's >>>>> only called from WADebugErrorHandler. >>>>> >>>>> >>>>>> b) it seems "Halt halt" does not work but sending a message that >>>>>> causes dnu does work. Maybe related to WADebugErrorHandler. >>>>>> >>>>> >>>>> I guess problem is that while MessageNotUnderstood is indeed a >>>>> subclass of Error, Halt is not. Anyway, the real problem is that with >>>>> halt, >>>>> the hooked method #openDebuggerOn: is not called... I tried to find out >>>>> which method handled Halt but I failed. >>>>> >>>>> >>>>> c) what happens if we have multiple debuggers opened? I am worried >>>>>> about the "soleInstance" of ProcessSpecificVariable. >>>>>> >>>>>> >>>>>> Thoughts? Can you tell me if this works for you? >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> On Fri, Dec 4, 2015 at 1:13 PM, Max Leske <maxle...@gmail.com> wrote: >>>>>> >>>>>>> >>>>>>> On 04 Dec 2015, at 17:11, Mariano Martinez Peck < >>>>>>> marianop...@gmail.com> wrote: >>>>>>> >>>>>>> I found a way!!!! Much cleaner and easier. Awesome! >>>>>>> I will clean it, test it a bit more and try to package it for public >>>>>>> usage :) >>>>>>> >>>>>>> >>>>>>> Give me a snippet! I want to play with it! :D >>>>>>> >>>>>>> >>>>>>> On Fri, Dec 4, 2015 at 12:31 PM, Mariano Martinez Peck < >>>>>>> marianop...@gmail.com> wrote: >>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> On Fri, Dec 4, 2015 at 12:05 PM, Max Leske <maxle...@gmail.com> >>>>>>>> wrote: >>>>>>>> >>>>>>>>> >>>>>>>>> On 04 Dec 2015, at 14:29, Mariano Martinez Peck < >>>>>>>>> marianop...@gmail.com> wrote: >>>>>>>>> >>>>>>>>> Max...Seaside uses WADynamicVariable (NOT DynamicVariable) which >>>>>>>>> are completely different. WADynamicVariable uses exception >>>>>>>>> mechanism while DynamicVariable uses the ProcessSpecificVariable. >>>>>>>>> But thanks anyway! >>>>>>>>> >>>>>>>>> >>>>>>>>> Oh man…. Sorry :) >>>>>>>>> >>>>>>>>> I wonder, why WADynamicVariable *isn’t* a DynamicVariable. The >>>>>>>>> semantics are the same if I’m not mistaken (e.g. only available in the >>>>>>>>> current process) and I think access to a dynamic variable may even be >>>>>>>>> faster because it *doesn’t* use the exception mechanism (i.e. no need >>>>>>>>> to >>>>>>>>> walk down the stack). >>>>>>>>> If someone knows the answer, I’d be happy to hear it. >>>>>>>>> >>>>>>>>> >>>>>>>> I bet it's because of portability. For example, i remember in >>>>>>>> GemStone the ProcessorLocalVariable did not behave the same as in >>>>>>>> Pharo. >>>>>>>> And it was actually an experiment. I think you cannot expect all this >>>>>>>> stuff >>>>>>>> to be ansi (or easily portable), while exceptions do. >>>>>>>> >>>>>>>> >>>>>>>>> I’ve played around with Process>>signalException: and >>>>>>>>> Context>>handleSignal: (which looked quite promising) but didn’t get >>>>>>>>> any >>>>>>>>> results. I’m out of ideas. >>>>>>>>> >>>>>>>>> >>>>>>>> I have played all morning with an idea of using local variables. I >>>>>>>> arrive to the point where I DO HAVE the request context at hand, but I >>>>>>>> don't find an easy way to hook into do-its, print-it etc so that the >>>>>>>> closure evaluated gets the request context plugged. In other ways... >>>>>>>> let's >>>>>>>> say I have the context stored somewhere. I am at the SmalltalkEditor >> >>>>>>>> evaluateSelectionAndDo: aBlock >>>>>>>> >>>>>>>> and so..somewhere I need to do something like: >>>>>>>> >>>>>>>> WACurrentRequestContext use: self storedContextSomewhere during: [ >>>>>>>> self theSelectionToBeEvaluated ] >>>>>>>> >>>>>>>> and that's where I am now :) >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>>> Cheers, >>>>>>>>> Max >>>>>>>>> >>>>>>>>> >>>>>>>>> On Fri, Dec 4, 2015 at 7:32 AM, Max Leske <maxle...@gmail.com> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>>> Here’s a snippet to play with: >>>>>>>>>> >>>>>>>>>> p := Processor activeProcess. >>>>>>>>>> x := 2. >>>>>>>>>> v := TestDynamicVariable value: x during: [ >>>>>>>>>> ((p instVarNamed: 'env') ifNotNil: [ :env| >>>>>>>>>> env copyWithout: nil ]) inspect >>>>>>>>>> ]. >>>>>>>>>> >>>>>>>>>> ((p instVarNamed: 'env') ifNotNil: [ :env| >>>>>>>>>> env copyWithout: nil ]) inspect >>>>>>>>>> >>>>>>>>>> Cheers, >>>>>>>>>> Max >>>>>>>>>> >>>>>>>>>> On 04 Dec 2015, at 10:47, Max Leske <maxle...@gmail.com> wrote: >>>>>>>>>> >>>>>>>>>> I feel you :) >>>>>>>>>> >>>>>>>>>> Without having thought this through completely: if you look at >>>>>>>>>> the implementation of DynamicVariable>>value:during: you’ll see that >>>>>>>>>> the >>>>>>>>>> way it works is that the variable is bound to the active process. In >>>>>>>>>> the >>>>>>>>>> debugger you have access to the process that is being debugged and >>>>>>>>>> thus you >>>>>>>>>> should have access to the variables bound to it. You could try >>>>>>>>>> accessing >>>>>>>>>> all such variables by iterating over them (which I think will >>>>>>>>>> require an >>>>>>>>>> extension on Process because you’d need to access at least the >>>>>>>>>> PSKeys class >>>>>>>>>> variable). >>>>>>>>>> >>>>>>>>>> Cheers, >>>>>>>>>> Max >>>>>>>>>> >>>>>>>>>> On 04 Dec 2015, at 00:34, Mariano Martinez Peck < >>>>>>>>>> marianop...@gmail.com> wrote: >>>>>>>>>> >>>>>>>>>> Hi guys, >>>>>>>>>> >>>>>>>>>> This thing I will ask in this email it's in my mind since YEARS. >>>>>>>>>> But I have always thought it was like that and that there was >>>>>>>>>> nothing we >>>>>>>>>> could do. However, I think it's time I ask again :) >>>>>>>>>> >>>>>>>>>> For those that have used Seaside, and you try to debug, you know >>>>>>>>>> that upon request processing seaside uses Exceptions mechanisim to >>>>>>>>>> always >>>>>>>>>> have access to the request, session, etc. They way that is done is >>>>>>>>>> very >>>>>>>>>> smart :) >>>>>>>>>> >>>>>>>>>> WACurrentRequestContext use: self during: aBlock >>>>>>>>>> >>>>>>>>>> In that case, "self" is the request instance and aBlock the >>>>>>>>>> closure that takes care of the request processing. So, inside that >>>>>>>>>> closure, >>>>>>>>>> everywhere you do "WACurrentRequestContext value" you get the correct >>>>>>>>>> request instance. >>>>>>>>>> >>>>>>>>>> So..that's great for Seaside, but debugging gets complicated. >>>>>>>>>> While you can restart, proceed, etc, once inside debugger, you >>>>>>>>>> cannot >>>>>>>>>> evaluate any piece of code that will use the session or request >>>>>>>>>> because >>>>>>>>>> you get a WARequestContextNotFound. Of course, because I guess the >>>>>>>>>> evaluation you do from cmd+d on a piece of text or via the debugger >>>>>>>>>> inspector, creates another closure/context which does not receive the >>>>>>>>>> WACurrentRequestContext instance. >>>>>>>>>> >>>>>>>>>> Now....besides WACurrentRequestContext I have my own class >>>>>>>>>> UserContextInformation where I basically have a bunch of stuff >>>>>>>>>> associated >>>>>>>>>> to the logged user. And I do exactly the same as the >>>>>>>>>> WACurrentRequestContext. And I have the same problem. I really want >>>>>>>>>> to be >>>>>>>>>> able to fix this. >>>>>>>>>> >>>>>>>>>> Anyone have an idea on how can I do it? I guess I can change the >>>>>>>>>> debugger, in the place where I evaluate code so that I wrap that >>>>>>>>>> evaluation >>>>>>>>>> with my request context instance??? >>>>>>>>>> >>>>>>>>>> Thoughts? >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>>>>>> Mariano >>>>>>>>>> http://marianopeck.wordpress.com >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> -- >>>>>>>>> Mariano >>>>>>>>> http://marianopeck.wordpress.com >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> -- >>>>>>>> Mariano >>>>>>>> http://marianopeck.wordpress.com >>>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>>> -- >>>>>>> Mariano >>>>>>> http://marianopeck.wordpress.com >>>>>>> >>>>>>> >>>>>>> >>>>>> >>>>>> >>>>>> -- >>>>>> Mariano >>>>>> http://marianopeck.wordpress.com >>>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> Mariano >>>>> http://marianopeck.wordpress.com >>>>> >>>> >>>> >>>> >>>> -- >>>> Mariano >>>> http://marianopeck.wordpress.com >>>> >>> >>> >>> >>> -- >>> Mariano >>> http://marianopeck.wordpress.com >>> >> >> >> >> -- >> Mariano >> http://marianopeck.wordpress.com >> > > > > -- > Mariano > http://marianopeck.wordpress.com > > > -- Mariano http://marianopeck.wordpress.com