Fix datadir handling #15864

pull hebasto wants to merge 7 commits into bitcoin:master from hebasto:20190421-datadir-handling changing 7 files +26 −18
  1. hebasto commented at 8:44 PM on April 21, 2019: member

    Fix #15240, see: #15240 (comment) Fix #15745 Fix broken feature_config_args.py tests (disabled by MarcoFalke@fabe28a0cdcfa13e0e595a0905e3642a960d3077). All test are enabled now. This PR is alternative to #13621.

    User's $HOME directory is not touched unnecessarily now.

    ~To make reviewing easier only bitcoind code is modified (neither bitcoin-cli nor bitcoin-qt).~

    Refs:

  2. hebasto cross-referenced this on Apr 21, 2019 from issue bitcoind wont start with datadir specified in conf file and no home dir by d3spwn
  3. fanquake added the label Utils/log/libs on Apr 21, 2019
  4. in src/util/system.cpp:793 in e7bf2899ce outdated
     788 | @@ -784,7 +789,8 @@ void ClearDatadirCache()
     789 |  
     790 |  fs::path GetConfigFile(const std::string& confPath)
     791 |  {
     792 | -    return AbsPathForConfigVal(fs::path(confPath), false);
     793 | +    fs::path path = fs::path(confPath);
     794 | +    return path.is_absolute() ? path : AbsPathForConfigVal(path, false);
    


    promag commented at 10:45 PM on April 21, 2019:

    Is this necessary? Looks like fs::absolute already does this in AbsPathForConfigVal.


    hebasto commented at 4:12 AM on April 22, 2019:

    Yes, it is needed to not touch default datadir unnecessarily, before all configs are read.


    ryanofsky commented at 3:06 PM on April 29, 2019:

    It seems like a better fix (simpler and more general) would be to add:

    if (path.is_absolute()) return path;
    

    as the first line of AbsPathForConfigVal.

  5. in src/util/system.cpp:778 in e7bf2899ce outdated
     772 | @@ -773,6 +773,11 @@ const fs::path &GetDataDir(bool fNetSpecific)
     773 |      return path;
     774 |  }
     775 |  
     776 | +bool CheckDataDirOption()
     777 | +{
     778 | +    return gArgs.IsArgSet("-datadir") ? fs::is_directory(fs::system_complete(gArgs.GetArg("-datadir", ""))) : true;
    


    promag commented at 10:49 PM on April 21, 2019:

    This doesn't check the default data dir.


    hebasto commented at 4:14 AM on April 22, 2019:

    You are right. This behavior is intentional.


    ryanofsky commented at 6:50 PM on May 7, 2019:

    You are right. This behavior is intentional.

    Would be helpful to say what the function is supposed to do in the header. Maybe

    //! Return true if -datadir value points to a valid directory or was not specified.
    

    It might be also be less confusing to write this as:

    return !gArgs.IsArgSet("-datadir") || fs::is_directory(fs::system_complete(gArgs.GetArg("-datadir", "")))
    

    ryanofsky commented at 7:01 PM on May 7, 2019:

    In commit "Add CheckDataDirOption() function" (a45f692366d7bb4814af83e3b645c9e5a5a734e6)

    I don't think IsArgSet is the right function to call here. If somebody has a datadir option specified in the config file, but wants to unset it on the command line by passing -nodatadir or -datadir="", it seems like this should be allowed. Would suggest:

    std::string datadir = gArgs.GetArg("-datadir", "");
    return datadir.empty() || fs::is_directory(fs::system_complete(datadir));
    

    And a corresponding change in GetDataDir()


    hebasto commented at 4:14 PM on May 9, 2019:

    I don't think IsArgSet is the right function to call here. If somebody has a datadir option specified in the config file, but wants to unset it on the command line by passing -nodatadir or -datadir="", it seems like this should be allowed.

    Good catch! Agree.

  6. hebasto commented at 4:19 AM on April 22, 2019: member

    @promag Thank you for your review. To be clear, the premature address to the default datadir, until possible -datadir option is read from the config file(s), is the root of all issues fixed by this PR.

  7. hebasto cross-referenced this on Apr 22, 2019 from issue unexpected behavior when specify datadir in config file by huahuayu
  8. promag commented at 10:01 AM on April 22, 2019: member

    On my system:

    # create a file in the default data dir
    touch "/Users/joao/Library/Application Support/Bitcoin"
    
    # launch with default data dir
    src/bitcoind
    
    
    ************************
    EXCEPTION: N5boost10filesystem16filesystem_errorE
    boost::filesystem::create_directory: File exists: "/Users/joao/Library/Application Support/Bitcoin"
    bitcoin in AppInit()
    
    Assertion failed: (globalChainBaseParams), function BaseParams, file chainparamsbase.cpp, line 30.
    [1]    53221 abort      src/bitcoind
    
  9. hebasto commented at 5:38 PM on April 22, 2019: member

    @promag

    On my system:

    # create a file in the default data dir
    touch "/Users/joao/Library/Application Support/Bitcoin"
    
    # launch with default data dir
    src/bitcoind
    
    
    ************************
    EXCEPTION: N5boost10filesystem16filesystem_errorE
    boost::filesystem::create_directory: File exists: "/Users/joao/Library/Application Support/Bitcoin"
    bitcoin in AppInit()
    
    Assertion failed: (globalChainBaseParams), function BaseParams, file chainparamsbase.cpp, line 30.
    [1]    53221 abort      src/bitcoind
    

    The same behavior is observed on master as well. This PR does not change it.

  10. hebasto cross-referenced this on Apr 23, 2019 from issue Handle exception when creating default -datadir by promag
  11. DrahtBot commented at 11:47 AM on April 28, 2019: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #16224 (gui: Bilingual GUI error messages by hebasto)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  12. ryanofsky commented at 3:09 PM on April 29, 2019: contributor

    This comment doesn't seem to be true: #15864#issue-272240173

    To make reviewing easier only bitcoind code is modified (neither bitcoin-cli nor bitcoin-qt).

    Since GetConfigFile is called all three places. It would also seem worrying if this were true, since it would mean the different binaries wouldn't behave consistently.

  13. hebasto force-pushed on Apr 29, 2019
  14. hebasto commented at 8:58 PM on April 29, 2019: member

    @ryanofsky Thank you for your review. Your comment has been addressed. Also commits for bitcoin-qt and tools (bitcoin-cli, bitcoin-wallet) have been added.

    Would you mind re-reviewing?

  15. in src/util/system.cpp:1212 in f46eec4f80 outdated
    1225 | @@ -1226,6 +1226,9 @@ int64_t GetStartupTime()
    1226 |  
    1227 |  fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific)
    1228 |  {
    1229 | +    if (path.is_absolute()) {
    


    ryanofsky commented at 6:43 PM on May 7, 2019:

    In commit "Return absolute path early in AbsPathForConfigVal" (f46eec4f80117ce242ed8c86b6216ece3eb20fba)

    It would be helpful if the commit message said why this change was being made. Is this an optimization or is it preventing an error or does it have some other effect on behavior?


    hebasto commented at 3:48 PM on May 9, 2019:

    Fixed.

  16. in src/bitcoind.cpp:95 in 160470f76f outdated
      94 | @@ -95,8 +95,7 @@ static bool AppInit(int argc, char* argv[])
      95 |  
      96 |      try
      97 |      {
      98 | -        if (!fs::is_directory(GetDataDir(false)))
      99 | -        {
     100 | +        if (!CheckDataDirOption()) {
    


    ryanofsky commented at 7:11 PM on May 7, 2019:

    In commit "Fix datadir handling in bitcoind" (160470f76f22edd1f9ef6448584381fc5626b9c4)

    I can't figure out what this commit is doing. Is it fixing #15745 or #15864? Is the idea to prevent the datadir from being cached here? Can you write in the commit description what problem this is fixing and how it works?


    hebasto commented at 6:51 PM on July 5, 2019:

    Please see #15864 (comment)

  17. ryanofsky approved
  18. ryanofsky commented at 7:46 PM on May 7, 2019: contributor

    utACK c4ab7420ef5dc4e6925519f8571a936f38720862. It's not really clear to me which bugs are being fixed by these changes, and how exactly the fixes work, but the basic idea seems to be to avoid calling GetDataDir() various places early on startup when it isn't necessary, to avoid caching bad values.

    The changes seem worth making as optimizations or for clarity regardless of the bugs. But it'd also make sense as followup to look into:

    • Whether caching datadir is a useful optimization
    • Whether it makes sense to interpret a non-absolute "-conf" argument relative to the datadir

    Both of these seem questionable to begin with.

  19. hebasto commented at 3:30 PM on May 9, 2019: member

    @ryanofsky

    It's not really clear to me which bugs are being fixed by these changes, and how exactly the fixes work, but the basic idea seems to be to avoid calling GetDataDir() various places early on startup when it isn't necessary, to avoid caching bad values.

    The root of the reported bugs (#15240, #15745) is GetDataDir() tries to create data directory. This step is premature when config file has not been read yet.

  20. hebasto force-pushed on May 9, 2019
  21. promag commented at 4:35 PM on May 9, 2019: member

    I think we could replace the directory creation with an assertion (that datadir already exists) and create the directory right before the first call to GetDataDir() - probably on init.

  22. hebasto force-pushed on May 9, 2019
  23. hebasto commented at 6:23 PM on May 9, 2019: member

    @promag

    I think we could replace the directory creation with an assertion (that datadir already exists) and create the directory right before the first call to GetDataDir() - probably on init.

    Is it a bit out of the scope of this PR?

  24. hebasto commented at 6:24 PM on May 9, 2019: member

    @ryanofsky All your comments have been addressed.

  25. in src/util/system.cpp:744 in 5df1581b9e outdated
     752 | @@ -753,8 +753,9 @@ const fs::path &GetDataDir(bool fNetSpecific)
     753 |      if (!path.empty())
     754 |          return path;
     755 |  
     756 | -    if (gArgs.IsArgSet("-datadir")) {
     757 | -        path = fs::system_complete(gArgs.GetArg("-datadir", ""));
     758 | +    std::string datadir = gArgs.GetArg("-datadir", "");
    


    ryanofsky commented at 7:37 PM on May 9, 2019:

    In commit "Add CheckDataDirOption() function" (5df1581b9ee6f13593b33fa9629ea9fbadcad732)

    Ideally commit message might also mention that it changes the behavior of the GetDataDir function. The effect I think is to now allow -nodatadir or -datadir='' options on the command line to override any datadir specified in the config file and reset it to default. In theory this could even be mentioned in release notes, but it's probably too niche.


    hebasto commented at 9:31 PM on May 26, 2019:

    The effect I think is to now allow -nodatadir or -datadir='' options on the command line to override any datadir specified in the config file and reset it to default.

    Unfortunately, neither -nodatadir nor -datadir='' on the command line cannot unset datadir specified in the config file or reset it to default. See: #16097.


    MarcoFalke commented at 10:56 PM on July 2, 2019:

    Then, why is this changed?


    hebasto commented at 7:57 PM on July 5, 2019:

    The initial idea was:

    I don't think IsArgSet is the right function to call here.

    If we recall: https://github.com/bitcoin/bitcoin/blob/8c69fae94410f54bad13be0f34d54370fddbf4b3/src/util/system.cpp#L470-L474

    using IsArgNegated is (logically) inappropriate for -datadir option, IMO.

    Also (but minor), the suggested code uses only one function call (GetArg) instead of two calls (IsArgSet and GetArg).


    hebasto commented at 4:30 PM on July 24, 2019:

    @ryanofsky @MarcoFalke

    The effect I think is to now allow -nodatadir or -datadir='' options on the command line to override any datadir specified in the config file and reset it to default.

    Actually, with this PR -datadir='' (with empty string) or -datadir will reset it to default. So, going to close #16416 in favor of this PR.

  26. ryanofsky approved
  27. ryanofsky commented at 7:51 PM on May 9, 2019: contributor

    utACK 9bddf12763e1bcc41c176f8b7f0b883efed49823. Changes since last review are adding commit descriptions, documenting new CheckDataDirOption() method, and handling -nodatadir and -datadir="" better.

    This PR should be tagged as needing release notes if release notes aren't added before it is merged in a doc/release-notes-15864.md file. I think you could take the description from #15864 (comment) and basically turn it into a release note, describing the class of bugs that are fixed and not mentioning specific function names.

  28. hebasto cross-referenced this on Jun 16, 2019 from issue odd behaviour of GetDataDir creating wallets/ subdirectory by markblundeberg
  29. hebasto commented at 10:57 PM on June 16, 2019: member

    @MarcoFalke would you mind reviewing this PR?

  30. hebasto force-pushed on Jun 17, 2019
  31. hebasto commented at 3:56 PM on June 17, 2019: member

    Rebased after #16205 merged.

  32. MarcoFalke commented at 5:18 PM on June 17, 2019: member

    Concept ACK

  33. MarcoFalke cross-referenced this on Jun 27, 2019 from issue util: Remove code to cache datadir by MarcoFalke
  34. ryanofsky approved
  35. ryanofsky commented at 6:44 PM on June 27, 2019: contributor

    utACK 4f0de6214ae591bfb37ef745140f45fcc97aec33. No changes since last review except rebase and replacing fprintf with tfm::format.

  36. DrahtBot added the label Needs rebase on Jun 28, 2019
  37. hebasto force-pushed on Jun 28, 2019
  38. hebasto commented at 7:36 PM on June 28, 2019: member

    Rebased on top of #16300.

  39. in src/util/system.cpp:1214 in c21150fd6f outdated
    1198 | @@ -1199,6 +1199,9 @@ int64_t GetStartupTime()
    1199 |  
    1200 |  fs::path AbsPathForConfigVal(const fs::path& path, bool net_specific)
    1201 |  {
    1202 | +    if (path.is_absolute()) {
    1203 | +        return path;
    1204 | +    }
    


    MarcoFalke commented at 7:55 PM on June 28, 2019:

    Would be nice if each commit had a test that failed before compilation and passes after. That might simplify review, no?


    hebasto commented at 3:33 AM on June 29, 2019:

    Do tests enabled in 5124b1cef24a9b30876ddedf922dfdb555bd4ace do this job?


    MarcoFalke commented at 6:38 PM on July 8, 2019:

    Can they be enabled in this commit (the first commit)?


    hebasto commented at 7:16 PM on July 8, 2019:

    Do you mean to combine the "Enable all tests in feature_config_args.py " commit (5124b1cef24a9b30876ddedf922dfdb555bd4ace) into the "Return absolute path early in AbsPathForConfigVal" commit (c21150fd6f598196fae93cf4bddc6e7625a43660)?

    Master branch plus this combined commit will fail the test. And the test will be passed on top of the 584621f9a81b6cc547c8f1365f1b358866e9a335 and b921f6ee951f0ad6d87eeeb372136a7314af0b0e commits.

    Did I understand your intention correctly?

  40. DrahtBot removed the label Needs rebase on Jun 28, 2019
  41. ryanofsky approved
  42. ryanofsky commented at 6:35 PM on July 8, 2019: contributor

    utACK 5f55360ea36487131a14dbc0a2518ec3babc1580. No changes since last review other than rebase and comment tweak.

  43. DrahtBot added the label Needs rebase on Jul 8, 2019
  44. hebasto force-pushed on Jul 10, 2019
  45. hebasto commented at 5:03 PM on July 10, 2019: member

    Rebased.

  46. DrahtBot removed the label Needs rebase on Jul 10, 2019
  47. hebasto commented at 12:52 PM on July 13, 2019: member

    @laanwj Would you mind reviewing this PR?

  48. ryanofsky approved
  49. ryanofsky commented at 5:30 PM on July 15, 2019: contributor

    utACK fd7310f24422901e0d4cf82c93f04b2b1b458865. No changes since last review other than rebase after #16291

  50. hebasto cross-referenced this on Jul 18, 2019 from issue -datadir or -datadir="" option implies default datadir by hebasto
  51. MarcoFalke commented at 10:50 PM on July 23, 2019: member

    The 09a307183aca7b2f6e1a14caf4430a1fc546e704 commit would have to be in the test commit or before it, otherwise the test running with the gui might fail on the test commit?

  52. hebasto force-pushed on Jul 23, 2019
  53. hebasto force-pushed on Jul 24, 2019
  54. hebasto force-pushed on Jul 24, 2019
  55. hebasto force-pushed on Jul 24, 2019
  56. hebasto force-pushed on Jul 24, 2019
  57. hebasto force-pushed on Jul 24, 2019
  58. DrahtBot added the label Needs rebase on Jul 24, 2019
  59. hebasto renamed this:
    Fix datadir handling
    WIP: Fix datadir handling
    on Jul 24, 2019
  60. Return absolute path early in AbsPathForConfigVal
    This prevents premature GetDataDir() calls, e.g., when config file is
    not read yet.
    c1f325126c
  61. Add CheckDataDirOption() function 740d41ce9f
  62. Fix datadir handling in bitcoind
    This prevents premature tries to access or create the default datadir.
    This is useful when the -datadir option is specified and the default
    datadir is unreachable.
    50824093bb
  63. hebasto force-pushed on Jul 24, 2019
  64. hebasto renamed this:
    WIP: Fix datadir handling
    Fix datadir handling
    on Jul 24, 2019
  65. Fix datadir handling in bitcoin-qt
    This prevents premature tries to access or create the default datadir.
    This is useful when the -datadir option is specified and the default
    datadir is unreachable.
    b28dada374
  66. Fix datadir handling in bitcoin-cli
    This prevents premature tries to access or create the default datadir.
    This is useful when the -datadir option is specified and the default
    datadir is unreachable.
    7e33a18a34
  67. Use CheckDataDirOption() for code uniformity
    All other clients and tools use CheckDataDirOption() rather
    fs::is_directory(GetDataDir(false)) for the first datadir check.
    66f5c17f8a
  68. hebasto commented at 4:11 PM on July 24, 2019: member

    Rebased. @MarcoFalke

    The 09a3071 commit would have to be in the test commit or before it, otherwise the test running with the gui might fail on the test commit?

    Commits have been rearranged. The test commit is the last one now.

  69. Enable all tests in feature_config_args.py ffea41f530
  70. hebasto force-pushed on Jul 24, 2019
  71. DrahtBot removed the label Needs rebase on Jul 24, 2019
  72. MarcoFalke added this to the milestone 0.19.0 on Aug 16, 2019
  73. MarcoFalke referenced this in commit 83112db129 on Aug 19, 2019
  74. MarcoFalke merged this on Aug 19, 2019
  75. MarcoFalke closed this on Aug 19, 2019

  76. sidhujag referenced this in commit 894dd2f309 on Aug 19, 2019
  77. hebasto deleted the branch on Aug 19, 2019
  78. hebasto commented at 1:52 PM on October 17, 2019: member

    @MarcoFalke #15240 (comment)

    Label "Needs backport 0.18" ?

  79. fanquake added the label Needs backport (0.18) on Oct 17, 2019
  80. ryanofsky cross-referenced this on Jan 9, 2020 from issue refactor: Implement missing error checking for ArgsManager flags by ryanofsky
  81. fanquake removed the label Needs backport (0.18) on Mar 13, 2020
  82. deadalnix referenced this in commit c5a632bec6 on Apr 22, 2020
  83. deadalnix referenced this in commit 68cb14deaa on Apr 23, 2020
  84. furszy cross-referenced this on Jan 17, 2022 from issue Improve PID file error and datadir handling by furszy
  85. furszy referenced this in commit 7b265f22e8 on Jan 20, 2022
  86. bitcoin locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-05-19 06:54 UTC