Saturday, June 2, 2007

Calling attribute setters from module

The question is, what is the output of the following ruby code:


module A
def set_x(y)
x=y
end
end

class B
attr_accessor :x
end

b = B.new
b.x=1
b.set_x(2)
puts b.x


The output is 1, and for first i expected the output to be 2.

A.set_x creates a new local variable x instead of calling the attribute setter, which is proabably a wise decision. Otherwise a module method that intends to use a local variable, might end up using an attribute setter. (If the class which includes the module has one.)

The workaround is to tell the module that you want to access the attribute setter with self.:


module A
def set_x(y)
self.x=y
end
end

Wednesday, April 25, 2007

Howto unload LaunchD deamon from itself

Launchd is cool. It can be used to watchdog your process by setting the OnDemand key to false in the launchd plist. This means that if your program exitst launchd will automatically restart it. But what happens if you want to stop the deamon on purpose?!
First you can unload it with using the following terminal command:

sudo launchctl unload /Libarary/LaunchDaemon/mydaemon.plist


But you can use the following class to programatically use the launchd api for a daemon to unload itself.
Usage is like this:

int main()
{
LaunchD ld;

while(...) {
if (needstop)
ld.Stop();
}
}




class LaunchD
{
public:
LaunchD()
{
startedWithLaunchD = false;
me = 0;
}

~LaunchD()
{
if (me) {
launch_data_free(me);
}
}

bool CheckIn(bool allowRunWithoutLaunchd = true)
{
launch_data_t msg, resp;
msg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
if ((resp = launch_msg(msg)) == NULL) {
if (allowRunWithoutLaunchd) {
startedWithLaunchD = false;
return false;
}
syslog(LOG_ERR,"Checkin with launchd failed: %m");
exit(EXIT_FAILURE);
}
launch_data_free(msg);
if (LAUNCH_DATA_ERRNO == launch_data_get_type(resp)) {
errno = launch_data_get_errno(resp);
if (errno == EACCES) {
syslog(LOG_ERR, "Check-in failed. Did you forget to set"
"ServiceIPC == true in your plist?");
} else {
syslog(LOG_ERR, "Check-in failed: %m");
}
exit(EXIT_FAILURE);
}
launch_data_t tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_LABEL);
me = launch_data_copy(tmp);
startedWithLaunchD = true;
if (tmp) {
syslog(LOG_ERR, "My job label:%s\n",launch_data_get_string(tmp));
}
return true;
}

bool Stop()
{
if (startedWithLaunchD) {
launch_data_t resp;
launch_data_t msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY);
if (! launch_data_dict_insert(msg,me,LAUNCH_KEY_REMOVEJOB)) {
syslog(LOG_ERR, "launch_data_dict_insert failed!\n");
return false;
}
if (! launch_data_dict_insert(msg,me,LAUNCH_KEY_STOPJOB)) {
syslog(LOG_ERR, "launch_data_dict_insert failed!\n");
return false;
}
if ((resp = launch_msg(msg)) == NULL) {
syslog(LOG_ERR, "launch_msg LAUNCH_KEY_STOPJOB failed!\n");
return false;
}
if (LAUNCH_DATA_ERRNO == launch_data_get_type(resp)) {
errno = launch_data_get_errno(resp);
if (errno == EACCES) {
syslog(LOG_ERR, "Stop request failed EACCESS!");
} else {
syslog(LOG_ERR, "Check-in failed: %m");
}
exit(EXIT_FAILURE);
}
launch_data_free(msg);
}
return true;
}
private:
bool startedWithLaunchD;
launch_data_t me;
};

Tuesday, January 9, 2007

IsItCarbonWindow or IsItCocoaWindow?!

I've found the following implementation:


@class NSCarbonWindow;

bool IsItACocoaWindow (WindowRef window)
{
NSWindow* cocoaWindow = [[NSWindow alloc] initWithWindowRef:window];
BOOL carbon = [[cocoaWindow class]isSubclassOfClass:[NSCarbonWindow class]];
[cocoaWindow release];
return !carbon;
}


bool IsItACarbonWindow (WindowRef window)
{
/* This one is a pure carbon function but it's a bit fragile, as for example in Leopard it actually returns: com.apple.hitoolbox.window.viewadapter */
CFStringRef classid = HIObjectCopyClassID ((HIObjectRef) window);
bool cocoa = (CFStringCompare (CFSTR ("com.apple.hitoolbox.window.external"), classid, 0) == kCFCompareEqualTo) ||
(CFStringCompare (CFSTR ("com.apple.hitoolbox.window. viewadapter"), classid, 0) == kCFCompareEqualTo);
CFRelease (classid);
return !cocoa;
}



It's also interesting to note that this can work because in case of the CocoaWindow the initWithWindowRef method will return the original window object for Cocoa objects. That is:


window == [[NSWindow alloc] initWithWindowRef: [window windowRef]];