Xcode C++ mkdir from Xcode in $HOME/Desktop hangs - APFS or Mojave bug?

/bin/cp and mkdir() in Xcode C++ in $HOME/Desktop both hang - suspect this points to a bug in Mojave or Libraries



Hi Team,



This is really wierd. The following code compiles on Xcode. Its behaviour is driving me nuts - so would appreciate anyone's help in

understanding what is going on as I would very much like to be able to create folders in my home directory with a c++ program.



The code is designed to create a path (if it does not already exist) and and a final file in that path.

Environment = 2012 MBPro running Mojave 10.14.4, and the latest version of XCode (10.2.1)

My home directory is "pwapwa".



Running XCode in debug mode, it causes Xcode to hang (using lots of cpu) at the point it is executing

mkdir pwa5

in the directory

/Volumes/MacBookII/Users/pwapwa/Desktop

In order to recover I have to kill Xcode.

XCode also hangs if I set

sSubPathName[4] = "Desktop1";

at the point it tries to execute

mkdir pwa5

after successfully creating "Desktop1".

It does not fail if I set

sSubPathName[4] = "Green1";

or if I then set

sSubPathName[7] = "pwapwa";

sSubPathName[8] = "Desktop";

sSubPathName[9] = "pwa1";

Conclusion:

mkdir causes Xcode to hang if it is used to create a subdirectory under

$HOME/Desktop*

where Desktop* is any combination of characters after the word Desktop or any subdirectory under $HOME/Desktop/



Similar weird behavior from /bin/cp

------------------------------------------

I note that /bin/mkdir works under all circumstances (although a version of /usr/local/bin/mkdir that used to work before upgrading to Mojave exhibits very similar behavior.)


/bin/cp -rf abc def

- where 'abc' is an empty folder and 'def' does not exist

- works if abc is in $HOME/abc

- does not work if abc is in $HOME/Desktop* or any subdirectory of $HOME/Desktop



I have reinstalled Xcode and Mojave (over existing filesystem) and get the same behavior.

I have changed reset permissions of my $HOME and subdirectories. Still mkdir and /bin/cp hang.



I suspect that somewhere in the libraries there is a test for "$HOME/Desktop" in the path of a file that is being created and a bug that results in the code hanging.

Please advise if this is peculirar to my installation (I have not yet checked it on other installations of Mojave or if it standard.

If anyne can explain why this happens please let me know.

It is crippling to my application if it cannot create folders anywhere under $HOME/Desktop directory.





------------------------------------------

//

// main.cpp

// TestMkDir

//

// Created by petera on 5/10/19.

// Copyright © 2019 petera. All rights reserved.

//



#include "sys/stat.h"

#include <iostream>

#include <string>

#include <fstream>

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <stdlib.h>



using namespace std;



void vBuildPathAndFile( string sSubPaths[], int iSubPaths, string sFileName ) {

char cCWD[2000];

int i;

string sCurrentPath;

struct stat sb;

bool bIsDirectory;

fstream sFptr;

string sFullPath;



sCurrentPath = "";



for (i = 0; i < iSubPaths; i++) {

getcwd(cCWD, 2000);

cout << "Current Working Directory Directory at start of loop: " << cCWD << "\n";

if (sSubPaths[i][0] != '/') {

sCurrentPath.append("/");

}

cout << "Adding [" << sSubPaths[i] << "]\n";;

sCurrentPath.append(sSubPaths[i]);

cout << "Directory to test: " << sCurrentPath << "\n";

if (stat(sCurrentPath.c_str(), &sb) == -1) { // File does not exist

cout << "Path [" << sCurrentPath << "] does not exist, will try and create it.\n";

if (mkdir(sSubPaths[i].c_str(), S_IRWXU) == 0) {

cout << "Path [" << sCurrentPath << "] was successfully created.\n";

} else {

cout << "Failed to create Path [" << sCurrentPath << "] - exit\n";

exit (-1);

}

} else { // It exists - now Check that is a directory

bIsDirectory = false;

switch (sb.st_mode & S_IFMT) {

case S_IFBLK: cout << "[" << sCurrentPath << "] is a block device\n"; break;

case S_IFCHR: cout << "[" << sCurrentPath << "] is a character device\n"; break;

case S_IFDIR:

cout << "[" << sCurrentPath << "] is a directory\n";

bIsDirectory = true;

break;

case S_IFIFO: cout << "[" << sCurrentPath << "] is a FIFO/pipe\n"; break;

case S_IFLNK: cout << "[" << sCurrentPath << "] is a symlink\n"; break;

case S_IFREG: cout << "[" << sCurrentPath << "] is a regular file\n"; break;

case S_IFSOCK: cout << "[" << sCurrentPath << "] is a socket\n"; break;

default: cout << "[" << sCurrentPath << "] is a unknown?\n"; break;

}

if (!bIsDirectory) {

cout << "[" << sCurrentPath << "] is not a directory - exit\n";

exit (-1);

}

}

chdir(sCurrentPath.c_str());



}

// If we got here - it is time to add the file

// Change to this path

chdir(sCurrentPath.c_str());

sFullPath = sCurrentPath + "/" + sFileName;

sFptr.open(sFileName.c_str(), fstream::out);

if (sFptr.is_open()) {

cout << "[" << sFullPath << "] was successfully created\n";

sFptr.close();

}

cout << "\n\nCheck if we can open another file with full path using open\n";

sFullPath = sCurrentPath + "/test2";

sFptr.open(sFullPath.c_str(), fstream::out);

if (sFptr.is_open()) {

cout << "[" << sFullPath << "] as a full path was successfully created\n";

sFptr.close();

} else {

cout << "[" << sFullPath << "] as a full path was NOT successfully created\n";

}

cout << "Check if we can open another file with full path that also has an non-existant folder in the path\n";

sFullPath = sCurrentPath + "/pwapwa0/test2";

sFptr.open(sFullPath.c_str(), fstream::out);

if (sFptr.is_open()) {

cout << "[" << sFullPath << "] as a full path was successfully created\n";

sFptr.close();

} else {

cout << "[" << sFullPath << "] as a full path was NOT successfully created\n";

}

cout << "We have used mkdir many times thus far to make each successive folder one at at time in the path\n";

cout << " Now will try and use mkdir to create one extra folder using the full path rather than the next directory\n";

sFullPath = sCurrentPath + "\nextFolder";

if (mkdir(sFullPath.c_str(), S_IRWXU) == 0) {

cout << "Path [" << sFullPath << "] was successfully created.\n";

} else {

cout << "Failed to create Path [" << sFullPath << "] - exit\n";

exit (-1);

}

}



int main(int argc, const char * argv[]) {

string sSubPathName[10];

string sFileName;

int iSubPaths;



sSubPathName[0] = "/Volumes";

sSubPathName[1] = "MacBookII";

sSubPathName[2] = "Users";

sSubPathName[3] = "pwapwa";

sSubPathName[4] = "Desktop";

sSubPathName[5] = "pwa5";

sSubPathName[6] = "pwa4";

sSubPathName[7] = "pwa3";

sSubPathName[8] = "pwa2";

sSubPathName[9] = "pwa1";

iSubPaths = 10;

sFileName = "pwaFile.txt";

vBuildPathAndFile( sSubPathName, iSubPaths, sFileName );

return 0;

}

Replies

I'm sorry, but you have a long list of things to do before you can even start to look at the code.


Where to start?


First of all, no one know how your system is configured. Your biggest problem seems to be with the Desktop. Do you have iCloud Documents and Desktop enabled? Or what about any number of 3rd party sync services? Don't tell me the answer. It is irrelevent. You should be testing in /tmp. If it works fine there and failed on Desktop, then you know there is something strange going on with Desktop. If you only test with Desktop, who knows?


Next, if your code is failing or hanging, please indicate where that is happening. You can't just say "mkdir". That doesn't mean anything. You call mkdir twice.


Next, don't call stat. Just attempt to do whatever it is you need to do. If it succeeds, move on with your life. If it fails, then deal with the failure.


What's the deal with "extFolder"? Is that supposed to be "nextFolder"? Or do you really want a file with a newline in it?


Why are you hard coding a path to your home directory? And why are you using /Volumes as the root? Neither is correct.


Why create a C array of strings and pass that to a function with a literal that just happens to be the length of the C array? If you want to use C++, use C++.


I can assure you that the problem is not in Mojave nor in any libraries.

Hi John,


Thanks for response and helpful comments. I have been an apple customer since the first apple][ was available in Australia. I have written code for 40 years (including some kernel stuff when I wokred at SGI). I have spent days trying to understand why code that I wrote some time ago worked when compiled and run in Sierra but did not work when I recompiled it using Xcode in Mojave. I do not understand this behavior or how to further debug it.

I really did try and debug this at my end ..... but have run out of ideas.


That is why i asked for help.


The code was written as a test harness so may not be perfect and can be used to test building paths in many drives and locations. Hence I am able to quickly test what works and what does not.


Running the code creates the path for

/tmp/MacBookII/Users/pwapwa/Desktop/pwa5/pwa4/pwapwa/Desktop/pwa1

where /tmp previously existed. So it works with /tmp


It works for the folders below and any subdirectories under them

/Users/pwapwa/tmp/

/Users/pwapwa/tmp/pwapwa/Desktop

/Users/pwapwa/Documents/

/tmp


Xcode hangs on the call to mkdir (i.e., never returns from the call) if I try and create a directory in a path that includes:

/Users/pwapwa/Desktop

/Users/pwapwa/Desktop1

/Users/pwapwa/DesktopXYZ

/Volumes/MacbookII/Users/pwapwa/Desktop


where /Volumes/MacbookII is the main ssd. To recover, I have to force XCode to quit (under Apple->Force Quit


Running the code also hangs if the code is run with $HOME/Desktop in terminal, either as user pwapwa or under sudo.

In both cases I have to kill the terminal app.

It seems that the thing that causes the problem is having /Users/pwapwa/Desktop in the path.

I am not aware of any sync servers running.

I tried reinstalling the OS (not a completely fresh reinstall - it was installed over existing system) and XCode (may not have delete all Xcode libraries) . No change.

I did accidently turn on iCloud and then turned it off again when I reinstalled the OS.

The problem occurred before and after the reinstall.

I tried changing permissions on Desktop to 777 - no change.

Tried resetting permissions in pwapwa/Desktop - no change.

In other words I have spent days trying to understand what is causing this.

The reason I use /Volumes in the full path is that the code that I am working on may create folders in external drives. If there is a better way - please let me know. In either case the code changes directories so that the mkdir normally only creates a single folder (and not the full path). Mkdir should work in all of these cases anyway.


I wonder if sandboxing has anything to do with teh problem???


I note that the desktop GUI routines work fine to create and copy files.

Existing programs work properly (except so far for /bin/cp - which hangs when copying folders under $HOME/Desktop.

I will try and simplify the code if that helps you understand the problem better and I will create a completely fresh install to test this problem.

It would be very useful for someone at apple to compile the code and test it. Would probably take a few minutes. However it will take me an hour to create a new Mojave install to test it there. If it works there, then that eliminates a lot and what is left is someething in my environment.

What in my environment could cause the problem - I have no idea unless it is some weird security issue.


Any other suggestions would be much appreciated.


Cheers,

Peter Arnold

The code [...] can be used to test building paths in many drives and locations.


I guess not.


Is the app sandboxed? I can't imagine it would be as that would prevent any of this from working.


As far as I can tell, your machine is hosed but good. If you've been hacking around on directory permissions, you can safely assume that it is never going to be useful as a test environment again. I strongly encourge you to wipe the hard drive, reinstall the operating system, and don't migrate anything back over. Use only iCloud to setup your account.


For any future testing, make sure to use a virtual machine instead. You can easily reset the virtual machine and test again in a pristine environment.


As for the code, I'm afraid it is a total loss. Creating directories is not difficult. You didn't answer most of my questions, including the one about the newline in the file name. You can replace the entire thing with a single call to /bin/mkdir. Time is money. If you've already spent days on it, don't throw good money after bad.