I've decided it's finally time for Armory to manage its own bitcoind instance. Instead of having the user start bitcoind/Bitcoin-Qt and wait for it to sync,
then start Armory. Armory will actually require bitcoind/-qt to
not be running, so that it can start its own bitcoind instance (and setup the RPC interface if it's not setup yet). It would then use the RPC interface to monitor bitcoind's progress sync'ing.
This will be a major usability upgrade -- the user will spend the same amount of time getting from week-old cold boot to having a synchronized bitcoind+Armory but they didn't have to do any of the work. And it will also likely be a better experience than Bitcoin-Qt, since Armory likes to
explain things to the user, so that they have some idea of what's going on and what to expect. Armory will be able to estimate how long until bitcoind is synchronized, and tell the user how it's only a one-time synchronization and future loads will be much faster, etc. And it will only connect "the old way" when it's fully sync'd (which resolves more usability problems, because users get impatient and open Armory prematurely and it chokes).
However, I'm having some serious problems with the implementation. I can't reliably guarantee that bitcoind is shutdown, especially if Armory were to crash. So here's what I've got right now:
- I have added a SatoshiDaemonManager to Armory. It will autodetect .bitcoin dir and find the bitcoind executable.
- If bitcoin.conf does not exist, it creates it and sets the permissions to 600 (Linux only, still need to figure out windows)
- Use the subprocess module to launch: "sdm.bitcoind = subprocess.Popen([pathToBitcoind, arg1, arg2, ...])"
- Include a call to sdm.bitcoind.terminate() in the shutdown procedure to do a clean shutdown of bitcoind before exiting cleanly.
Now's the hard part: dealing with unclean shutdowns. subprocess.Popen() creates a fork that doesn't necessary go away when the parent process does. I've been doing testing in Linux, and it seems to be inconsistent. But it definitely can leave a ghost bitcoind running which then blocks the user's attempt to restart Bitcoin-Qt or Armory.
The really challenging part of this is that I think I can make a solution work in Linux, but it is most definitely not cross-platform. And Windows is even more complicated, well, because it's windows.
One thing I had considered was wrapping Armory itself with an outer script that will run Armory itself in a subprocess, wait for it to quit/die, then check whether the process it spawned is still open and kill it if necessary (will write out the PID when Popen is called, to a file in ARMORY_HOME_DIR, which the outer script can check for after the Armory subprocess exits). The nice thing about this solution is that even if Armory segfaults, the outer script will finish running.
However, it's not so clear how easy this will be in windows (which has a totally different process management system), and it certainly will require an OS-dependent code branch -- and both may be kinda complicated. I presume it will work, it just may be a lot of effort...
Another solution could be to just check for open Bitcoin-Qt/bitcoind when Armory is started, and ask the user if they are willing to restart it. This is probably not going to work, because it would allow them to reopen Armory, but prevent them from opening Bitcoin-Qt after Armory dies (on the upside, it's good for creating competitive advantage for Armory
)
An ideal solution would be to find a way to create a subprocess that is linked to the current process -- if the current process goes away for any reason, the subprocess should too. So far, I don't see a clean way to do that. It looked like process id groups were the solution in Linux, but may not have an equivalent in Windows.
By the way: I
will have an option to just use an existing bitcoind/Bitcoin-Qt instance, but most users, especially those who have never used Bitcoin, will benefit
dramatically from having this as the default, all-in-one, standalone solution. It will probably show up in the preferences to "Allow using existing already-open Bitcoin-Qt/bitcoind instances".
Recommendations, welcome!