Repository: sunpy/sunpy

Issue:
Using SunPy in two threads sometimes crashes when creating config
I test HelioPy on two threads at the same time, and when it comes to importing SunPy the following error happens sporadically:

```
heliopy\coordinates\test\test_transformations.py:1: in <module>
    import heliopy.coordinates.frames as frames
heliopy\coordinates\frames.py:19: in <module>
    import sunpy.coordinates.sun
c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\sunpy\__init__.py:47: in <module>
    config = load_config()
c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\sunpy\util\config.py:30: in load_config
    config_files = _find_config_files()
c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\sunpy\util\config.py:69: in _find_config_files
    config_path = Path(_get_user_configdir())
c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\sunpy\util\config.py:137: in _get_user_configdir
    if not _is_writable_dir(configdir):
c:\hostedtoolcache\windows\python\3.6.8\x64\lib\site-packages\sunpy\util\config.py:123: in _is_writable_dir
    Path(p).mkdir(parents=True)
c:\hostedtoolcache\windows\python\3.6.8\x64\lib\pathlib.py:1253: in mkdir
    self.mkdir(mode, parents=False, exist_ok=exist_ok)
c:\hostedtoolcache\windows\python\3.6.8\x64\lib\pathlib.py:1248: in mkdir
    self._accessor.mkdir(self, mode)
c:\hostedtoolcache\windows\python\3.6.8\x64\lib\pathlib.py:387: in wrapped
    return strfunc(str(pathobj), *args)
E   FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'C:\\Users\\VssAdministrator\\AppData\\Local\\sunpy\\sunpy'
```

I think the solution is to change `Path(p).mkdir(parents=True)` to `Path(p).mkdir(parents=True, exist_okay=True)`


Discussion:
Can I ask how you run in two threads?

Resolving patch:
diff --git a/sunpy/util/config.py b/sunpy/util/config.py
--- a/sunpy/util/config.py
+++ b/sunpy/util/config.py
@@ -119,9 +119,13 @@ def _is_writable_dir(p):
     """
     Checks to see if a directory is writable.
     """
-    if not Path(p).exists():
-        Path(p).mkdir(parents=True)
-    return Path(p).is_dir() and os.access(p, os.W_OK)
+    # Worried about multiple threads creating the directory at the same time.
+    try:
+        Path(p).mkdir(parents=True, exist_ok=True)
+    except FileExistsError:  # raised if there's an existing file instead of a directory
+        return False
+    else:
+        return Path(p).is_dir() and os.access(p, os.W_OK)
 
 
 def _get_user_configdir():


Test patch:
diff --git a/sunpy/util/tests/test_config.py b/sunpy/util/tests/test_config.py
--- a/sunpy/util/tests/test_config.py
+++ b/sunpy/util/tests/test_config.py
@@ -13,7 +13,13 @@
 
 def test_is_writable_dir(tmpdir, tmp_path):
     assert _is_writable_dir(tmpdir)
-
+    tmp_file = tmpdir.join("hello.txt")
+    # Have to write to the file otherwise its seen as a directory(?!)
+    tmp_file.write("content")
+    # Checks directory with a file
+    assert _is_writable_dir(tmpdir)
+    # Checks a filepath instead of directory
+    assert not _is_writable_dir(tmp_file)
 
 def test_get_user_configdir(tmpdir, tmp_path, undo_config_dir_patch):
     # Default