Compile error: /usr/include/signal.h:92:1: error: unknown type name 'procset_t' on SmartOS and ruby 2.3.0

Issue #236 resolved
kigster
created an issue

Issue

Unfortunately, pg gem currently fails to compile on SmartOS against ruby 2.3. It builds against ruby 2.2.4.

Solution

After digging through compile output and various Solaris build reports from other projects, trying million things to get it built, I was able to build it by doing the following:

  • cd to the ext folder where previous build failed.
  • edit Makefile, and append -D__EXTENSIONS__ to the CPPFLAGS field, resulting in this:
CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\"
  -I/opt/local/include
  -I/home/app/.rbenv/versions/2.3.0/include
  -std=iso9899:1999
  -D_XOPEN_SOURCE=700
  -D__EXTENSIONS__ $(DEFS) $(cppflags)

After this modification, running make and make install completes installation of this gem.

Details

I am deploying a Rails application, which is syntax-level dependent on ruby 2.3.0 on SmartOS (an open source descendant of the former Solaris OS https://smartos.org/), and I am running into a surprising compile issue.

This issue happens only when building with ruby 2.3.0, which I previous installed from the sources on the same OS using rbenv.

When I use package-supplied ruby 2.2, the gem installs without any problem. Unfortunately, at this time Joyent does not offer ruby 2.3.0 package, which is why I resort to building it from sources. That said, it builds cleanly without any issues.

Here is what I know:

  • pg gem installs against ruby 2.2 provided by Joyent via a package
  • pg gem breaks with the complication error against ruby 2.3 compiled from sources
  • here is the actual error as it happens during gem install pg -- --with-pg-config=/opt/local/bin/pg_config.
compiling gvl_wrappers.c
In file included from /usr/include/poll.h:41:0,
     from /home/app/.rbenv/versions/2.3.0/include/ruby-2.3.0/ruby/io.h:36,
     from pg.h:85,
     from gvl_wrappers.c:6:
/usr/include/signal.h:92:1: error: unknown type name 'procset_t'
Makefile:238: recipe for target 'gvl_wrappers.o' failed

However, during another compilation attempt, different file triggered the same error:

compiling pg_copy_coder.c
In file included from /usr/include/poll.h:41:0,
     from /usr/local/include/ruby-2.3.0/ruby/io.h:36,
     from pg.h:85,
     from pg_copy_coder.c:6:
/usr/include/signal.h:92:29: error: unknown type name 'procset_t'
 extern int sigsendset(const procset_t *, int);
                             ^
Makefile:238: recipe for target 'pg_copy_coder.o' failed
make: *** [pg_copy_coder.o] Error 1

So the error happens in the same place – it's unable to find the symbol procset_t.

Now, I followed the include files starting from line 41 in poll.h, and that file includes sys/procset.h which does indeed define this symbol, but it's surrounded by two #defines:

here is a complete header file

/*
 *  The following defines the operations which can be performed to
 *  combine two simple sets of processes to form another set of
 *  processes.
 */
#if !defined(_XPG4_2) || defined(__EXTENSIONS__)
.....
..... /* procset_t definition follows */

I did a quick search on these symbols, and found this helpful thread: http://stackoverflow.com/questions/1034587/how-does-xpg4-2-and-other-defines-work-on-solaris

Basically, they are saying that Solaris has an interesting way of including various features into the compiled binary, which are controlled by -D flags. The above discussion recommends adding the following defines:

-D_XOPEN_SOURCE=1 -D_XOPEN_SOURCE_EXTENDED=1

I looked at the Makefile, and noticed that it already sets D_XOPEN_SOURCE=700, so I spent good amount of time trying to add the second flag -D_XOPEN_SOURCE_EXTENDED=1, to no avail. Now I was getting a very interesting message:

(output removed for brevity)
/usr/include/sys/feature_tests.h:387:2: error: #error "Compiler or options invalid for pre-UNIX 03 X/Open applications  and pre-2001 POSIX applications"
In file included from /usr/include/poll.h:41:0,
   from /home/app/.rbenv/versions/2.3.0/include/ruby-2.3.0/ruby/io.h:36,
   from pg.h:85,
   from pg_type_map_in_ruby.c:7:
/usr/include/signal.h:92:1: error: unknown type name 'procset_t'
Makefile:238: recipe for target 'pg_type_map_in_ruby.o' failed

At this point I understood that I am fighting with Solaris features/compiled combination pairings, or something along those lines, and so I went back to the failing header file, and there was only one more flag to try: -D__EXTENSIONS__

I thought that the -D_XOPEN_SOURCE_EXTENDED=1 is, perhaps, responsible for setting __EXTENSIONS__, but as it turns out – no, it's not. And so I went ahead and just added the -D__EXTENSIONS__ to the CPPFLAGS and ran make, everything compiled without a single warning:

app@app100  ~/.rbenv/versions/2.3.0/lib/ruby/gems/2.3.0/gems/pg-0.18.4/ext   master  make
compiling pg_copy_coder.c
compiling pg_type_map_all_strings.c
compiling pg_type_map_in_ruby.c
compiling util.c
compiling pg_type_map_by_column.c
compiling pg_text_decoder.c
compiling pg_text_encoder.c
compiling gvl_wrappers.c
compiling pg.c
compiling pg_type_map_by_oid.c
compiling pg_errors.c
compiling pg_binary_decoder.c
compiling pg_type_map_by_mri_type.c
compiling pg_type_map_by_class.c
compiling pg_binary_encoder.c
compiling pg_result.c
compiling pg_connection.c
compiling pg_type_map.c
compiling pg_coder.c
linking shared-object pg_ext.so

Now, this is obviously a workaround, so I am hoping that someone figures out what is going on.

  • Is the issue in how I built ruby 2.3.0 from sources? Is ruby config supposed to provide those defines to the extensions? I am not sure.

I will say one thing:

Feature Request

I found it very frustrating that there could be no way, other than manually modifying Makefile, to play with various options on the gem command line. I really wanted to do something like this:

CPPFLAGS="-D__EXTENSION__" gem install pg

OR

gem install pg -- --cppflags=-D__EXTENSIONS__

etc. I think it would be really nice to give users of the gem ways to supply various compile options without having to go and find the sources. Make it only available to power users, put it in the advanced README hidden inside a Makefile (LOL), but leave it there so that it's possible.

Thank you very much for building and maintaining this lovely gem. Using it and PostgreSQL since 2004.

Konstantin https://github.com/kigster

Comments (19)

  1. Michael Granger repo owner

    Hey, thanks for the lovely and detailed description of the problem. I'll look into your feature suggestion; mkmf is somewhat of a black box, but I think it should be possible to do what you suggest. If not, I can add that CPPFLAG when uname is smartos/solaris-ish.

  2. Filip Hajny

    Yes, please add __EXTENSIONS__ to CPPFLAGS to fix build with Ruby 2.3 on any SunOS platform.

    procset_h is only defined on SunOS for legacy pre-XPG4v2 code or if SunOS extensions are requested. However, as of Ruby 2.3.0, the default CPPFLAGS set the standard to 200809L (via _XOPEN_SOURCE=700) unconditionally, so you need to go the other way around this.

    (Speaking for Joyent/SmartOS.)

  3. Martin Carpenter

    Hi, I've hit the same issue in other gems (eg unf_ext) so was wondering if perhaps this should be addressed upstream in ruby's mkmf?

    Fumbling around with the macros very much like the OP I managed to build a SIGSEGV-happy ruby-pg (which is what brought me here); doubtless other folks will fumble this in other modules.

    Or is there some reason this isn't mkmf's fault?

  4. Michael Granger repo owner

    I think you're right @MartinCarpenter, but I don't know enough about the OS in question to submit it upstream. I'd also like to make it possible to use pg without the change if possible.

    I've looked around, but I couldn't find a definitive source for what I should be looking for in RUBY_PLATFORM to detect the OSes in question. Does anyone on this thread know?

  5. DANoWAR

    Hello,

    this issue is still unsolved, at least on

    • OS: Solaris 11.3 x86
    • Ruby: 2.3.1
    • Rubygems: 2.6.6
    • Postgres: 9.5.3
    • pg: 0.18.4

    Still have to

    • manually edit the Makefile (insert the -D__EXTENSIONS__)
    • make

    • make install

    to make it work...

    After doing it this way, the gem pg doesn't show up when I type gem list -l

  6. Michael Granger repo owner

    The fix isn't in a released version of the library yet. I thought I'd released it already, but I dropped the ball. I'll rectify that by Friday.

    As for make install: that installs the extension as a library instead of a gem, so gem -l won't show it but you can still require pg. You can do gem install pg --pre to get a prerelease of 0.19 that includes the fix.

  7. DANoWAR

    I have installed the prerelease. When I want to install the dependencies of Redmine 3.3.0 via "bundle install", bundler still wants to download and compile pg 0.18.4. I haven't found the step to take to tell bundler to instead use the prerelease version. Can you help?

    EDIT: To whoever wants to know this after googling...

    I solved my problem by changing the application Gemfile. It required pg as "~>0.18.1". I had to change it to ">=" to allow 0.19 and to "0.18.1.beta" to allow the prerelease.

  8. Log in to comment