20091202

Apple, part I

In June of 2009, I applied to work at Apple. A few weeks later, I got a call from an Apple recruiter, and we scheduled a first-round phone interview. I passed that one, and he called to schedule a second-round phone interview. I passed that one, too, and he called to schedule an in-person third-round interview.
By now it was mid-August. I took a day off of work to interview with 6-7 different Apple engineers, each for 45 minutes. I talked with them, showed them what I knew and what I could do in terms of coding and theory. The group leader told me I'd hear back by the end of the week. I thanked them, and went home.
I made a mistake, in that I didn't immediately send a "thank you" email; I waited a few days to do so.
The week ended, and I hadn't heard anything. I thought perhaps I misheard, and he'd said the end of the following week. Still nothing. No phone call, no email.
The next week, now 2.5 weeks after my interview, I emailed to ask if there was anything I could give them -- references, or further background, or anything -- to help them decide. The following was the entirely of the response I received, without the names:

Sorry [me]. Unfortunately, the team decided to pass on your candidacy.

[recruiter]

20090731

Core Foundation meets C++

I am tired of dealing with Core Foundation ornerinesses in a program primarily written in C++, so I decided to write a library of RAII wrappers for Core Foundation classes I use commonly.

My first problem was that I didn't really understand about overloading assignment operators, but I think I've figured them out now.

The next concern is that for many types, there are mutable and immutable version, which differ only by a const in their typedef to the opaque underlying type. My first thought was to implement, for example, CFMutableArrayRef and CFArrayRef wrappers separately.

My next thought was to set up some kind of inheritance.
Inheritance fails, however. If we want to say that the wrapper for the immutable inherits from the mutable, and makes some member functions/operators private, then we'll run into the problem that an instance of a derived class must be able to function as an object of the base class, and a derived class wrapping an immutable object cannot act the same as a base object that is mutable.

Third try: Make the private data member mutable, but provide a const "conversion operator" that will make it act like it's immutable. This seems like the best option so far.

I am planning to make the library available once it's usable. I am still deciding on the licensing system I wish to use, but I think I am leaning toward BSD-style, or maybe Creative Commons.

20090726

C string to CFString

I have a null-terminated string of (random) ASCII chars that I need to convert to a CFString for an API call. However, the following call yields NULL:

CFStringRef convertedValue = CFStringCreateWithCString(kCFAllocatorDefault, c_string, kCFStringEncodingUTF8);

According to the doc, this means "there was a problem creating the object."
I am currently stumped as to why.

20090715

launchd confusion

Does the following documentation indicate that one may not fork()/exec() in a launchd process? I'm certainly getting strange console messages when I do, but it's not clear yet if that's due to malformed code or if it's because of the way launchd treats children of children processes.

Citation: launchd documentation

Creating and running a launchd job

Whether you're migrating a job to launchd from some other system job launcher, or you're setting up a job for a new service, there are a few basic requirements for the job.

Jobs run from launchd should not duplicate launchd functionality; for instance, they should not use chroot(2). Furthermore, they should not do the things normally required of daemon processes, such as detaching from the terminal they are initially attached to. The only things that are strictly prohibited, however, are fork()/exit() combinations (including indirect methods, such as the daemon(3) library call). A server which attempts to run itself as a daemon in this way will seem to have finished running, potentially leading to launchd respawning it, or disabling the service. As launchd does not get stalled waiting for a child that hasn't yet exited, it's not necessary to try to prevent it.

20090714

CFFork

It is absolutely forbidden to use Core Foundation or higher-level APIs in a child process after fork()ing, before exec*()ing. This royally messes up our process model.

citation: OS X Leopard Core Foundation Release Notes

CoreFoundation and fork()
Due to the behavior of fork(), CoreFoundation cannot be used on the child-side of fork(). If you fork(), you must follow that with an exec*() call of some sort, and you should not use CoreFoundation APIs within the child, before the exec*(). The applies to all higher-level APIs which use CoreFoundation, and since you cannot know what those higher-level APIs are doing, and whether they are using CoreFoundation APIs, you should not use any higher-level APIs either. This includes use of the daemon() function.

Additionally, per POSIX, only async-cancel-safe functions are safe to use on the child side of fork(), so even use of lower-level libSystem/BSD/UNIX APIs should be kept to a minimum, and ideally to only async-cancel-safe functions.

This has always been true, and there have been notes made of this on various Cocoa developer mailling lists in the past. But CoreFoundation is taking some stronger measures now to "enforce" this limitation, so we thought it would be worthwhile to add a release note to call this out as well. A message is written to stderr when something uses API which is definitely known not to be safe in CoreFoundation after fork(). If file descriptor 2 has been closed, however, you will get no message or notice, which is too bad. We tried to make processes terminate in a very recognizable way, and did for a while and that was very handy, but backwards binary compatibility prevented us from doing so.

20090707

cfstring parsing

Why are strings so annoying?

I'm trying to take integer values from a c-string, but only if it's well-formed. Using CFNumberFormatterGetValueFromString works if I can correctly determine the boundaries of the number portions. The difficulty is determining where those are. The formatter still gives a value if the range contains, for example, 5e. The desired behavior is for it to return false is such a situation.

Can anyone recommend a better way to parse a CFString, so that I can determine if the string is well-formed, and get the values if so?

Edit: traversed the c-string, finding ranges and delimeters by hand.

20090628

Elevated Processes

Objective-c is an insecure language. Although the feature is being deprecated (I believe starting with Snow Leopard), a user may override a program's code.

An application that needs to perform a restricted action can prompt the user for Administrator password using the Security framework. However, for security reasons, the best methodology is to have a helper application, and launch it using the authorization obtained. This raises issues of setting +s on the helper tool and interprocess communication. Allegedly, all of these are very straightforward, but the Apple-provided BetterAuthorizationSample project is written in somewhat arcane C (there are goto statements!), and I find it very difficult to understand what's going on.

I would appreciate assistance, especially in the form of a non-Apple tutorial or documentation, indicating how to set up communication with an executable that is a secondary target in the same xcodeproj.

EDIT: Have now gotten helper application to launch. There was a typo in the filepath I passed to AEWP.

20090617

FSGetCatalogInfoBulk

I use this call to iterate over directory contents with fewer system calls. Sometimes, I delete files, and I need to open the iterator with kFSIterateDelete. The implementation is such that kFSIterateFlat was supposed to be able to permit such a delete-file operation, but does not in fact.
While testing the code, we commented out the actual delete, and found that the last n files in the directory were improperly processed. When we commented the delete back in, everything was cleared up.
The moral here is clear: When you open an FSIterator with the kFSIterateDelete flag, make sure to delete the files!

20090602

core foundation file manager

It's fun to reduce one problem to an already-solved problem.
I was working to remove all uses of the NSFileManager and replace them with faster CF file manager calls. I have one last function to fix, and even that is done (sans debugging) except that it relies on being able to determine if a file exists at a path held in a CFStringRef. I have a function

bool MyClass::fileExistsAtPath(NSString *filePath)
{
  return [[NSFileManager defaultManager] fileExistsAtPath:filePath];
}

but I want it to be

bool MyClass::fileExistsAtPath(CFStringRef path)
{
  return ???;
}

I have been searching the documentation, and I thought I could use a CFURL for this, but so far, I don't see any API that will tell me whether the url is valid.

20090527

awakeFromNib

What does awakeFromNib actually mean? Using the Cocoa principle of "it's probably what it sounds like," a naive programmer would assume that this method is invoked when the program awakes, i.e. receives focus. Alas, this is far from accurate. Someone seems to think that an object created via nib file instead of programmatically requires extra code, and that's possibly true; but "awake from nib?" Where's the waking up?

A nib file is an xml archive that in a sense dehydrates Cocoa objects for runtime reconstitution. However, it can require further tweakage, so every thus-created object receives the awakeFromNib message. It can be useful, for instance, in establishing connections; the app delegate manager receives awakeFromNib before applicationDidFinishLaunching, so I use it to create some connections such as (instance variable) dockTile = [NSApp dockTile]; which I can then refer to everywhere else in my class, knowing that it will have a valid value immediately after the object is instantiated, before any other code can run.


- (void)awakeFromNib
{
  dockTile = [NSApp dockTile];
}

20090518

Cocoa app delegate

Programming with the Cocoa APIs has been a very strange experience for me. My first experience was on the iPhone with Cocoa Touch, and right when I had sort-of figured that out, I had to switch to OS X development.
Yesterday, I figured out how to badge dock icons. I found the appropriate documentation, but I still didn't understand, so I downloaded the sample project. Now I had proof of existance, but couldn't see how it was working. Finally, I opened the nib, and saw that the AppDelegate class was connected via Interface Builder as the NSApplication's delegate, and thus its delegate functions were called as appropriate.
I cannot figure out how to achieve this same goal programmatically, so I copied their method, and it does indeed work.

EDIT: the following is untested, but seems like it should work:
Create an instance of the delegate class, and in its -awakeFromNib method, insert the follwing code:
[NSApp setDelegate:self];

the end.