Postgres + Ruby + OSX=Multi Architectural Hell

Written by  on December 29, 2009

I was finally able to get my ruby/rails environment setup with my database of choice.

It wasnt easy as postgres will not build with more than one architecture at a time, I had gone through similar hell the last time I tried to build anything on OSX that had to compile against libraries made for different architectures. Fortunately the solution was relatively simple.

My database is running 64 bit and I use it for many other applications that are compiled against either multiple architectures including 64bit but also some which are 64 bit only.

Ruby on the other hand is compled for 32 bit which worked flawlessly on mysql and most of the other gems i installed when I got to the postgres it puked in weird ways and when I tried every third solution on the net it was always the same.

Bash-3.2# gem install pg
Building native extensions.  This could take a while...
ERROR:  Error installing pg:
ERROR: Failed to build gem native extension.

The bottom line from one of the only success stories that I found on the net was that you either built everything 64bit or nothing. Easy enough if you want to build all of your dependencies by yourself. The whole point of gems is to have the tools work for you. I wasnt really able to figure this out in the web full of people beating their heads on the same problem each harder than the other and each reaching the same it doesnt work conclusion but I had the fortune of getting completely away from the web long enough to realize that only the client and libraries needed to match the architecture and since all interaction between rails and the database went through a socket the architecture of the client didn’t have to be the same as the database.

so going back to my postgres source tree i did a

...postgresql-8.3.6# make distclean

and then reconfigured the database using the prefix /usr/local32

..postgresql-8.3.6# ARCHFLAGS='-arch i386' ./configure --prefix=/usr/local32/

Then I just had to tel ruby/gem to use the 32 bit libraries. Since ruby uses pg_config I made sure that the 32bit version is in the path first.

# PATH=/usr/local32/bin/:$PATH ARCHFLAGS='-arch i386' \
gem install pg  -- --with-pgsql-dir=/usr/local32/

And we are off but my god what at PITA.

p4_error: Could not gethostbyname for host

Written by  on December 1, 2009

For awhile now, we’ve been unable to run using the “-nolocal” flag to the mpirun command in order to execute our simulation across the slave nodes without also treating the master as a slave. When I would run with:

$ mpirun -nolocal -np 7 ./simulation 

I would see an error like the following:

p0_10460: p4_error: Could not gethostbyname for host hostname; may be. invalid name

Being lazy, I spent quite a bit of time trawling the intertubes looking for a canned solution and found many dead-ends talking about the resolver, nsswitch.com, etc/hosts, etc. So, I finally sighed and reluctantly pulled out my programming hat and wrote the following:

#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <malloc.h>
int main(int argc, char *argv[])
{
  char *user_host = calloc(32, sizeof(char));
  int error = gethostname(user_host,32);
  if (error != 0) {
    printf("gethostname failed with error %d\n", error);
    return error;
  } else
    printf("user_host = %s\n", user_host);

  struct addrinfo *res0, hint;
  memset(&hint, 0, sizeof(hint));
  hint.ai_family = PF_UNSPEC;
  hint.ai_flags = AI_CANONNAME;
  error = getaddrinfo(user_host, NULL, &hint, &res0);
  if (error != 0) {
    printf("getaddrinfo failed with error %d.\n", error);
  }

  struct hostent *he;
  he = gethostbyname(user_host);
  if (!he) 
    printf("gethostbyname(gethostname()) failed\n");
  else
    printf("gethostbyname(gethostname()) = %s\n", he->h_name);

  free(user_host);
  user_host = "hostname";
  he = gethostbyname(user_host);
  if (!he) 
    printf("hostname(/*hardcoded*/ \"hostname\") failed\n");
  else
    printf("hostname(/*hardcoded*/ \"hostname\") = %s\n", he->h_name);
  return 0;
}

And that showed me that the string returned by gethostname() was flawed in some way… some insidiously evil and occult way that doesn’t show up on the terminal screen. Redirecting the output to a file and editing that file with vi showed me that there was a SPACE on the end of the string returned by gethostname(). Ugh.

Other symptoms you might see if you have cruft in your /etc/hostname entry:

sudo: unable to resolve host
hostname => hostname
hostname -f => Unknown host
hostname -a => Unknown host