Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

‘reload’ doesn't restart Yi #515

Closed
Fuuzetsu opened this issue Feb 4, 2014 · 22 comments
Closed

‘reload’ doesn't restart Yi #515

Fuuzetsu opened this issue Feb 4, 2014 · 22 comments
Labels

Comments

@Fuuzetsu
Copy link
Member

Fuuzetsu commented Feb 4, 2014

On my system, calling reload hangs Yi for a while (it's probably compiling config) and then kills it. I'd expect Yi to get restarted at this point but it doesn't.

32-bit Linux.

Does it work for anyone? Did it ever?

@Fuuzetsu
Copy link
Member Author

Fuuzetsu commented Feb 4, 2014

#160 is somewhat related.

@ethercrow
Copy link
Member

:reload using yi-vim2 config works for me on 64bit gentoo and 64bit os x, but M-x reload using yi-simple config shows error: WontCompile [GhcError {errMsg = "Could not find module Yi.Prelude'\nIt is a member of the hidden package yi-0.6.7.0'."}]

@Fuuzetsu
Copy link
Member Author

Fuuzetsu commented Feb 5, 2014

Hm, I just tried :reload with vim config and it worked for the basic case while with my emacs config I have the effect described in the OP.

Regarding that compile error, it sounds like you have an old install there, I just checked and any Yi.Prelude mentions were removed from any relevant Haskell files.

@codygman
Copy link

I had the same issue and ran Yi with --debug/tailed it:

cody@cody-G46VW:~/source/yi/yi/src$ tail -f ~/.yi.dbg 
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 3 >>> interactively
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 3 <<<
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 3 >>> interactively
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 3 <<<
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 10 time to render
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 10 refreshing screen.
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 10 startXs: [] 0 []
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 10 time to render
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 10 refreshing screen.
Tue, 11 Mar 2014 04:40:09 UTC ThreadId 10 startXs: [] 0 []
Tue, 11 Mar 2014 04:40:26 UTC ThreadId 9 pending events: 
Tue, 11 Mar 2014 04:40:26 UTC ThreadId 9 >>> interactively
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 9 <<<
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 9 pending events: 
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 9 >>> interactively
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 9 <<<
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 9 pending events: 
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 9 >>> interactively
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 9 <<<
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 10 time to render
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 10 refreshing screen.
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 10 startXs: [0] 17 []
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 10 time to render
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 10 refreshing screen.
Tue, 11 Mar 2014 04:40:28 UTC ThreadId 10 startXs: [0] 17 []
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 pending events: 
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 >>> interactively
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 <<<
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 time to render
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 refreshing screen.
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 startXs: [0] 17 []
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 pending events: 
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 >>> interactively
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 <<<
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 time to render
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 refreshing screen.
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 startXs: [0] 17 []
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 pending events: 
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 >>> interactively
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 <<<
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 time to render
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 refreshing screen.
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 startXs: [0] 17 []
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 pending events: 
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 >>> interactively
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 9 <<<
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 time to render
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 refreshing screen.
Tue, 11 Mar 2014 04:40:29 UTC ThreadId 10 startXs: [0] 17 []
Tue, 11 Mar 2014 04:40:31 UTC ThreadId 9 pending events: 
Tue, 11 Mar 2014 04:40:31 UTC ThreadId 9 >>> interactively
Tue, 11 Mar 2014 04:40:32 UTC ThreadId 9 errorEditor: Maybe.fromJust: Nothing

Then the list of places fromJust is used:

cody@cody-G46VW:~/source/yi/yi/src$ rgrep fromJust | grep -i -v vim
library/Yi/UI/Pango/Control.hs:import Data.Maybe (maybe, fromJust, fromMaybe)
library/Yi/UI/Pango/Control.hs:--      (%=) windowsA (fromJust . PL.move winIdx)
library/Yi/Editor.hs:swapWinWithFirstE = (%=) windowsA (swapFocus (fromJust . PL.moveTo 0))
library/Yi/Editor.hs:          Just ws' -> PL.insertLeft (ws ^. PL.focus) (fromJust $ PL.moveTo 0 ws')
library/Yi/Editor.hs:            assign tabsA (fromJust $ PL.moveTo tabIndex ts)
library/Yi/Editor.hs:            (%=) windowsA (fromJust . PL.moveTo winIndex)
library/Yi/Editor.hs:                      (%=) tabsA $ fromJust . PL.moveTo (pred count)
library/Yi/Editor.hs:                      assign tabsA $ fromJust newTabs
library/Yi/Editor.hs:      then (%=) tabsA (fromJust . PL.deleteLeft)
library/Yi/Editor.hs:      else (%=) windowsA (fromJust . PL.deleteLeft)
library/Yi/MiniBuffer.hs:                        (%=) windowsA (fromJust . PL.find initialWindow)
library/Yi/Dynamic.hs:import Data.Maybe(fromJust)
library/Yi/Dynamic.hs:                Just x -> fromJust $ D.fromDynamic x
library/Yi/Dynamic.hs:  --            Just x -> fromJust $ D.fromDynamic x
library/Yi/Dynamic.hs:                                   Just x -> fromJust $ fromDynamic x
library/Yi/Syntax/Haskell.hs:                      (flip notElem f . tokT . fromJust)
library/Yi/Syntax/Haskell.hs:                       (flip elem f . tokT . fromJust))
library/Shim/Hsinfo.hs:                         ((fst3 . fromJust) storedres `replaceWith` cres))) $
library/Shim/Hsinfo.hs:        ("fromJust","Maybe a -> a"),
library/Shim/Hsinfo.hs:       [("fromJust","Maybe a -> a"),("fromMaybe","a -> Maybe a -> a")]
cody@cody-G46VW:~/source/yi/yi/src$ 

My hunch is that Yi/Dynamic.hs is working with vim for some reason but not emacs, however it's unfounded. I'll be debugging this further later... have to get up for work early :/

@alanz
Copy link
Contributor

alanz commented Mar 21, 2014

I just replaced all of the above instances with lablelled calls to

gfromJust :: [Char] -> Maybe a -> a
gfromJust _info (Just h) = h
gfromJust  info Nothing = error $ "gfromJust " ++ info ++ " Nothing"

And still get

Fri, 21 Mar 2014 12:46:41 UTC ThreadId 558 pending events: 
Fri, 21 Mar 2014 12:46:41 UTC ThreadId 558 >>> interactively
Fri, 21 Mar 2014 12:46:42 UTC ThreadId 558 errorEditor: Maybe.fromJust: Nothing

So it must be in an imported library somewhere

@Fuuzetsu
Copy link
Member Author

Oh, that sucks a whole lot. I'm guessing it's in dyre somewhere such as Config/Dyre/Relaunch.hs:51: masterPath <- fmap fromJust getMasterBinary. I'll try to find some time to investigate this later today.

@alanz
Copy link
Contributor

alanz commented Mar 21, 2014

Yep, getMasterBinary is returning Nothing

On Fri, Mar 21, 2014 at 3:04 PM, Mateusz Kowalczyk <notifications@github.com

wrote:

Oh, that sucks a whole lot. I'm guessing it's in dyre somewhere such as Config/Dyre/Relaunch.hs:51:
masterPath <- fmap fromJust getMasterBinary. I'll try to find some time
to investigate this later today.

Reply to this email directly or view it on GitHubhttps://github.com//issues/515#issuecomment-38273930
.

@alanz
Copy link
Contributor

alanz commented Mar 21, 2014

I have spent some time digging through this, and it does not make sense.

The bug can be enabled / disabled by switch from the Vim keybindings to the emacs one.

I added some putStrLn to the getValue and putValue calls in System.IO.Storage

With the vim keymap I get the following

yiDriver:about to call wrapMain
withDyreOptions: storing masterBinary as:/home/alanz/.cache/yi/yi-linux-x86_64
System.IO.Storage.putValue :("dyre","masterBinary",Just "/home/alanz/.cache/yi/yi-linux-x86_64")
System.IO.Storage.putValue :("dyre","masterBinary",Just "/home/alanz/.cabal/bin/yi")
System.IO.Storage.putValue :("dyre","forceReconf",Nothing)
System.IO.Storage.putValue :("dyre","denyReconf",Nothing)
System.IO.Storage.putValue :("dyre","debugMode",Nothing)
System.IO.Storage.getValue :("dyre","persistState")
System.IO.Storage.getValue :("dyre","persistState",Nothing,Nothing)
reload about to relaunchWithBinaryState
System.IO.Storage.putValue :("dyre","persistState",Just "/tmp/13788.state")
relaunchWithBinaryState: saved state
relauncMaster, getting masterBinary
System.IO.Storage.getValue :("dyre","masterBinary")
System.IO.Storage.getValue :("dyre","masterBinary",Nothing,Nothing)
System.IO.Storage.getValue :("dyre","masterBinary")
System.IO.Storage.getValue :("dyre","masterBinary",Nothing,Nothing)
System.IO.Storage.getValue :("dyre","persistState")
System.IO.Storage.getValue :("dyre","persistState",Nothing,Nothing)
customExec: (binary,args)=("/home/alanz/.cabal/bin/yi",["--debug","-fpango","/home/alanz/.config/yi/yi.hs","--dyre-state-persist=/tmp/13788.state","--dyre-master-binary=/home/alanz/.cabal/bin/yi"])

With the emacs keymap I get the following

yiDriver:about to call wrapMain
withDyreOptions: storing masterBinary as:/home/alanz/.cache/yi/yi-linux-x86_64
System.IO.Storage.putValue :("dyre","masterBinary",Just "/home/alanz/.cache/yi/yi-linux-x86_64")
System.IO.Storage.putValue :("dyre","masterBinary",Just "/home/alanz/.cabal/bin/yi")
System.IO.Storage.putValue :("dyre","forceReconf",Nothing)
System.IO.Storage.putValue :("dyre","denyReconf",Nothing)
System.IO.Storage.putValue :("dyre","debugMode",Nothing)
System.IO.Storage.getValue :("dyre","persistState")
System.IO.Storage.getValue :("dyre","persistState",Nothing,Nothing)
reload about to relaunchWithBinaryState
System.IO.Storage.putValue :("dyre","persistState",Just "/tmp/14231.state")
relaunchWithBinaryState: saved state
relauncMaster, getting masterBinary
System.IO.Storage.getValue :("dyre","masterBinary")
System.IO.Storage.getValue :("dyre","masterBinary",Nothing,Nothing)

The two Nothing's printed out in getValue are attempts to cast the value to a String and to a FilePath

It seems that in the emacs case trying to reference the return value from getMasterBinary stops everything dead.

@Fuuzetsu
Copy link
Member Author

It seems that the vim case gets

System.IO.Storage.getValue :("dyre","masterBinary")
System.IO.Storage.getValue :("dyre","masterBinary",Nothing,Nothing)

twice, perhaps emacs simply gives up and vim keeps trying until something changes (binary becomes ready or something? Just a guess).

It is quite strange…

@alanz
Copy link
Contributor

alanz commented Mar 21, 2014

No, thats just an artifact of my quickndirty logging. The one is on ontry
to the function, the other on exit with result

On Fri, Mar 21, 2014 at 10:07 PM, Mateusz Kowalczyk <
notifications@github.com> wrote:

It seems that the vim case gets

System.IO.Storage.getValue :("dyre","masterBinary")
System.IO.Storage.getValue :("dyre","masterBinary",Nothing,Nothing)

twice, perhaps emacs simply gives up and vim keeps trying until something
changes (binary becomes ready or something? Just a guess).

It is quite strange...

Reply to this email directly or view it on GitHubhttps://github.com//issues/515#issuecomment-38317860
.

@benarmston
Copy link
Contributor

I believe the difference is in whether the reload command is run via execEditorAction. You can test this by starting yi as yi --as vim2 and then:

  1. running the command :reload. This runs the Yi.Boot.reload function directly and should quickly.
  2. running the command :yi reload. This compiles the string "reload" using the functionexecEditorAction and then runs the result.

In case (2) something seems to hang.

Making the following change

diff --git a/yi/src/library/Yi/Keymap/Emacs.hs b/yi/src/library/Yi/Keymap/Emacs.hs
index 1113456..99f60cd 100644
--- a/yi/src/library/Yi/Keymap/Emacs.hs
+++ b/yi/src/library/Yi/Keymap/Emacs.hs
@@ -15,6 +15,7 @@ module Yi.Keymap.Emacs (keymap,
                         completionCaseSensitive
                         ) where

+import {-# source #-} Yi.Boot (reload)
 import Control.Applicative
 import Control.Lens
 import Data.Prototype
@@ -277,5 +278,6 @@ emacsKeys univArg =
                  , char 'r'      ?>>  rectangleFuntions
                  , char 'u'      ?>>! repeatingArg undoB
                  , char 'v'      ?>>! repeatingArg shrinkWinE
+                 , char 'R'      ?>>! reload
                  , optMod ctrl (char 't') >> tabFunctions
                  ]

Would allow testing the same difference in the emacs key bindings. This time C-x R vs M-x reload.

@benarmston
Copy link
Contributor

I was hoping that the following change would fix this. Unfortunately, it doesn't. Something along these lines may work.

diff --git a/yi/src/library/Yi/Eval.hs b/yi/src/library/Yi/Eval.hs
index ed49df0..693dddb 100644
--- a/yi/src/library/Yi/Eval.hs
+++ b/yi/src/library/Yi/Eval.hs
@@ -28,6 +28,7 @@ import Data.Typeable
 import Data.Binary
 import Data.Default
 import qualified Language.Haskell.Interpreter as LHI
+import qualified Language.Haskell.Interpreter.Unsafe as LHI
 import System.Directory(doesFileExist)
 import qualified Data.HashMap.Strict as M

@@ -94,7 +95,7 @@ ghciEvaluator = Evaluator{..} where
     execEditorActionImpl s = do
        contextFile <- Yi.Paths.getEvaluatorContextFilename
        haveUserContext <- io $ doesFileExist contextFile
-       res <- io $ LHI.runInterpreter $ do
+       res <- io $ LHI.unsafeRunInterpreterWithArgs ["-no-user-package-db", "-package-db=.cabal-sandbox/x86_64-linux-ghc-7.6.3-packages.conf.d/"] $ do
            LHI.set [LHI.searchPath LHI.:= []]
            LHI.set [LHI.languageExtensions LHI.:= [LHI.OverloadedStrings,
                                                    LHI.NoImplicitPrelude -- use Yi prelude instead.

@benarmston
Copy link
Contributor

On further investigation the above changes to LHI are unlikely the problem as running the following works :yi insertN "foo".

@alanz
Copy link
Contributor

alanz commented Mar 22, 2014

Applying your patch results in it working for the C-x R variant, but not
M-x reload.

I was pretty sure it was related to how it is called, but I am still
confused as to the exact point it fails when it does not work, but maybe it
is because the IO output gets queued or something.

I suspect there are processes being forked which then violate the Dyre
expectations when it is invoked.

Alan

On Sat, Mar 22, 2014 at 3:22 AM, Ben Armston notifications@github.comwrote:

I believe the difference is in whether the reload command is run via
execEditorAction. You can test this by starting yi as yi --as vim2 and
then:

  1. running the command :reload. This runs the Yi.Boot.reload function
    directly and should quickly.
  2. running the command :yi reload. This compiles the string "reload"
    using the functionexecEditorAction and then runs the result.

In case (2) something seems to hang.

Making the following change

diff --git a/yi/src/library/Yi/Keymap/Emacs.hs b/yi/src/library/Yi/Keymap/Emacs.hsindex 1113456..99f60cd 100644--- a/yi/src/library/Yi/Keymap/Emacs.hs+++ b/yi/src/library/Yi/Keymap/Emacs.hs@@ -15,6 +15,7 @@ module Yi.Keymap.Emacs (keymap,
completionCaseSensitive
) where
+import {-# source #-} Yi.Boot (reload)
import Control.Applicative
import Control.Lens
import Data.Prototype@@ -277,5 +278,6 @@ emacsKeys univArg =
, char 'r' ?>> rectangleFuntions
, char 'u' ?>>! repeatingArg undoB
, char 'v' ?>>! repeatingArg shrinkWinE+ , char 'R' ?>>! reload
, optMod ctrl (char 't') >> tabFunctions
]

Would allow testing the same difference in the emacs key bindings. This
time C-x R vs M-x reload.

Reply to this email directly or view it on GitHubhttps://github.com//issues/515#issuecomment-38339345
.

@benarmston
Copy link
Contributor

I'm confused as to the exact point it fails too. I've just tested this with yi installed outside of a cabal sandbox. I had the same result as when yi is inside a cabal sandbox: :reload works whilst :yi reload hangs. So I'd say we can rule out Dyre having trouble with sandboxed builds being the root cause.

@alanz
Copy link
Contributor

alanz commented Mar 22, 2014

Just for completeness, I am testing the long way by doing a cabal install
each time, no sandbox.

I suspect it is related to some thread related processing in the minibuffer
mode, but have not looked at the source for it yet.

On Sat, Mar 22, 2014 at 10:38 AM, Ben Armston notifications@github.comwrote:

I'm confused as to the exact point it fails too. I've just tested this
with yi installed outside of a cabal sandbox. I had the same result as when
yi is inside a cabal sandbox: :reload works whilst :yi reload hangs. So
I'd say we can rule out Dyre having trouble with sandboxed builds being the
root cause.

Reply to this email directly or view it on GitHubhttps://github.com//issues/515#issuecomment-38346194
.

@ethercrow
Copy link
Member

If all else fails, we can resort to this:

diff --git a/yi/src/library/Yi/Eval.hs b/yi/src/library/Yi/Eval.hs
index ed49df0..b2b20d4 100644
--- a/yi/src/library/Yi/Eval.hs
+++ b/yi/src/library/Yi/Eval.hs
@@ -32,6 +32,7 @@ import System.Directory(doesFileExist)
 import qualified Data.HashMap.Strict as M

 import Yi.Config.Simple.Types
+import {-# source #-} Yi.Boot
 import Yi.Core
 import Yi.File
 import Yi.Hooks
@@ -91,6 +92,7 @@ exists, it is imported unqualified.
 ghciEvaluator :: Evaluator
 ghciEvaluator = Evaluator{..} where
     execEditorActionImpl :: String -> YiM ()
+    execEditorActionImpl "reload" = reload
     execEditorActionImpl s = do
        contextFile <- Yi.Paths.getEvaluatorContextFilename
        haveUserContext <- io $ doesFileExist contextFile

@alanz
Copy link
Contributor

alanz commented Mar 22, 2014

This does have the advantage of solving the problem :)

My 5c, I also think that reload is a very special case.

On Sat, Mar 22, 2014 at 12:27 PM, Dmitry Ivanov notifications@github.comwrote:

If all else fails, we can resort to this:

diff --git a/yi/src/library/Yi/Eval.hs b/yi/src/library/Yi/Eval.hsindex ed49df0..b2b20d4 100644--- a/yi/src/library/Yi/Eval.hs+++ b/yi/src/library/Yi/Eval.hs@@ -32,6 +32,7 @@ import System.Directory(doesFileExist)
import qualified Data.HashMap.Strict as M

import Yi.Config.Simple.Types
+import {-# source #-} Yi.Boot

import Yi.Core
import Yi.File
import Yi.Hooks@@ -91,6 +92,7 @@ exists, it is imported unqualified.
ghciEvaluator :: Evaluator
ghciEvaluator = Evaluator{..} where
execEditorActionImpl :: String -> YiM ()+ execEditorActionImpl "reload" = reload

 execEditorActionImpl s = do
    contextFile <- Yi.Paths.getEvaluatorContextFilename
    haveUserContext <- io $ doesFileExist contextFile

Reply to this email directly or view it on GitHubhttps://github.com//issues/515#issuecomment-38347979
.

@Fuuzetsu
Copy link
Member Author

I'll +1 the workaround if everyone gives up on searching for the fault

@codygman
Copy link

@alanz when you say:

"My 5c, I also think that reload is a very special case."

I am looking at Yi as a replacement for Emacs (with a more powerful extension language) and was planning to write a lot of extensions for it. For me and others who planned on doing the same, reload would be a very common case unless I misunderstand something.

For reference I got this error while doing this simple Yi extension tutorial:

http://www.nobugs.org/developer/yi/index.html

@alanz
Copy link
Contributor

alanz commented Mar 22, 2014

The special case I mean is that it is pretty much unique in all the
commands that would be used, in that it triggers the dynamic reload of the
whole thing.

As such, treating it as a special case makes sense, as it is in a class of
its own.

So use would be common, the code would only require a single special case.

On Sat, Mar 22, 2014 at 7:49 PM, codygman notifications@github.com wrote:

@alanz https://github.com/alanz when you say:

"My 5c, I also think that reload is a very special case."

I am looking at Yi as a replacement for Emacs and was planning to write a
lot of extensions for it. For me and others who planned on doing the same,
reload would be a very common case.

Reply to this email directly or view it on GitHubhttps://github.com//issues/515#issuecomment-38358732
.

@ethercrow
Copy link
Member

I've committed the workaround for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants