Latest Updates: programming RSS

  • Snakes on Demand: How to write a Python Launchd Agent

    mike 9:23 pm on March 14, 2010 | 0 Permalink | Reply
    Tags: launchd, , macdev, multiprocessing, programming, python

    Suppose you want to write a Launchd agent in Python that communicates using UNIX domain sockets. There’s no sample code for that, but the information is out there to figure out how (especially because the launchd source code is available). Most search results will tell you that you need to read the Daemons and Agents Tech Report TN2083, but it’s pretty long and not a great tutorial. A better intro reference is Chris Hanson’s blog post “Launchd: better than sliced bread!”, but that doesn’t tell you everything, and doesn’t mention Python.

    I decided I’d share what I’ve learned recently to make getting started a little easier. I’ll give a short description here and post the resulting code to bitbucket at py-launchd.

    Note: This was written and tested on OS X 10.5.8 with the default /usr/bin/python, version 2.5.1. Since I wanted to use multiprocessing, I used the backport to 2.5 available at google code: python-multiprocessing . For convenience, it’s included in the repository, and so is its license.

    Goal

    What we’re trying to do is have some python code that gets called when launchd notices someone connecting to a UNIX domain socket. UNIX domain sockets are local-only, so this is ideal for agents that only serve local apps. We’re also using launchd “agents” not “daemons”, so we’re assuming that it’s OK to have one agent process for each user. If you’re managing access to something that needs to be unique system-wide, then this won’t work (but you can still use Launchd).

    launchd overview

    The launchd process will read a launchd plist you give it (at login, via launchctl or the 10.6 framework), and listen on the socket you tell it to. Once it sees a connection, it’ll start the agent program you specified in the plist, and that program can make some calls using the launchd C API to get a file descriptor for the socket that was connected. This is important – you don’t need to call bind() or listen() on the socket, because launchd already did. It’s just handing the open socket’s file descriptor straight to you and your code can just call accept() on it.

    Using launchd with Python

    You need to create a C/ObjC tool that can do the launchd check-in to get the open file descriptor, then pass that off to your Python code. This is pretty straightforward using the Python framework included in OS X and the Python C APIs.

    What I’ve done is create an agent loader that I called PyLaunchd that loads and runs server code in Agent.py. It expects Agent.py to be in the same directory.

    PyLaunchd is built separately and copied into the test app’s Resources folder with an XCode script phase.

    I have the app delegate copy PyLaunchd and Agent.py to ~/Library/Application Support/PyLaunchd/ on loading. It also customizes the launchd plist to set the path correctly for the current user, then writes that to ~/Library/LaunchAgents/, and loads it. (Actually it first unloads it, then reloads it. I’m not convinced this is the right way to do it). It uses system() to call launchctl, but I believe in OS X 10.6 there’s an API you can call to do it directly.

    Finally, the sample app is really simple – it just opens the socket using the multiprocessing Client class, and sends whatever you type. The example Agent I’ve included will ROT13 it and send it back.

    Please let me know if you have any comments, questions, or improvements.

     
  • App History

    mike 1:02 pm on November 25, 2009 | 0 Permalink
    Tags: , programming

    I just saw Brent’s post from a couple weeks ago about an App History App – I think that’d be really cool. I especially like the screen shot idea, since I love seeing posts from a developer showing what an app looked like along the progression. It’s too easy to forget to document that kind of thing, and I’d love it if we saw more of these behind-the-scenes posts.

     
  • iCal's Text Field Jumble

    mike 2:38 pm on November 2, 2008 | 0 Permalink
    Tags: , , programming,

    I’ve written here before about text fields, particularly the problem of having a good-looking ‘display’ mode and a separate ‘edit’ mode for data you don’t edit so often, like in AddressBook.

    The most recent version of iCal decided that events are write-once-read-many as well. You now have to use cmd-E to get into edit mode, while cmd-I just gives you a small display mode.

    I’m mostly OK with that, although I find I edit events about as often as I look at their info windows – after editing I usually just deal with alarms, not the events themselves. The casual glance at the time and title is always enough – I think either you’re looking at the time and title or you’re editing. I don’t see the appeal in the new ‘info-only’ mode (if it’s actually new – it seems new.)

    However, the change does highlight the jumble of editable text fields and text-like fields in the edit window:

    The “Add Attendees” link and the “None” placeholder for url act the same – you click on them, and enter text. One’s a link and one’s mute gray text. Why? For my part, I think the gray text is too understated, and the link is too garish.

    There are other differences: you can tab to the “url” field, but you can’t tab to “attendees”… until you add one, then you can. Once you click on either of them, the url field pops up a plain white raised NSTextField, but the attendees field is sunken and translucent, apparently an NSTokenField?

    Both of the blue links could also be buttons. I’m still not completely sold on replacing buttons with links, but I can understand the trend. I think a small plus-sign button would be fine for “Add File”, though, and “Attendees” ought to be a text field. Why force the user to use the mouse when adding data to an event?

    All in all, I think the “Add Attendees” link/field is pretty strange. I’m curious if I missing a precedent somewhere.

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
esc
cancel