Project

General

Profile

Actions

Backport #8174

closed

AIX header file conflict with rb_hook_list_struct

Added by edelsohn (David Edelsohn) about 11 years ago. Updated about 11 years ago.


Description

=begin
rb_hook_list_struct defines a member "events":

typedef struct rb_hook_list_struct {
struct rb_event_hook_struct *hooks;
rb_event_flag_t events;
int need_clean;
} rb_hook_list_t;

AIX defines a macro "events" in sys/poll.h:

struct pollfd
{
long fd; /* file descriptor or file ptr /
ushort reqevents; /
requested events /
ushort rtnevents; /
returned events /
};
#define events reqevents /
SVR3,4 pollfd member name /
#define revents rtnevents /
SVR3,4 pollfd member name */

Ruby thread.c includes sys/poll.c via ruby/io.h. This renames the structure member when referenced through EXEC_EVENT_HOOK, e.g.,

    if ((state = EXEC_TAG()) == 0) {
        SAVE_ROOT_JMPBUF(th, {
            if (!th->first_func) {
                GetProcPtr(th->first_proc, proc);
                th->errinfo = Qnil;
                th->root_lep = rb_vm_ep_local_ep(proc->block.ep);
                th->root_svar = Qnil;
                EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, Qundef);
                th->value = rb_vm_invoke_proc(th, proc, (int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
                EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_END, th->self, 0, 0, Qundef);
            }

This makes the compiler unhappy:

compiling /usr/gnu/src/ruby-2.0.0-p0/thread.c
/usr/gnu/src/ruby-2.0.0-p0/thread.c: In function 'thread_start_func_2':
/usr/gnu/src/ruby-2.0.0-p0/thread.c:496:6: error: 'rb_hook_list_t' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c:496:6: error: 'rb_hook_list_t' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c:496:6: error: 'rb_hook_list_t' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c:496:6: error: 'rb_hook_list_t' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c: In function 'rb_threadptr_execute_interrupts':
/usr/gnu/src/ruby-2.0.0-p0/thread.c:1917:6: error: 'rb_hook_list_t' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c:1917:6: error: 'rb_hook_list_t' has no member named 'reqevents'

Because Ruby only uses fd member revents, one option is to change include/ruby/io.h

diff

#include "ruby/config.h"
#if defined(HAVE_POLL)

include <poll.h>

+# undef events

define RB_WAITFD_IN POLLIN

define RB_WAITFD_PRI POLLPRI

define RB_WAITFD_OUT POLLOUT

=end

Updated by nobu (Nobuyoshi Nakada) about 11 years ago

  • Description updated (diff)
  • Status changed from Open to Feedback

=begin
reqevents and rtnevents names are not mentioned in ((URL:http://pic.dhe.ibm.com/infocenter/aix/v7r1/topic/com.ibm.aix.basetechref/doc/basetrf1/poll.htm)).

Is this page old?

What about this patch?

diff --git i/include/ruby/io.h w/include/ruby/io.h
index 07be55c..12ffc76 100644
--- i/include/ruby/io.h
+++ w/include/ruby/io.h
@@ -29,6 +29,10 @@ extern "C" {

#include "ruby/config.h"
#if defined(HAVE_POLL)
+# ifdef _AIX
+# define reqevents events
+# define rtnevents revents
+# endif

include <poll.h>

define RB_WAITFD_IN POLLIN

define RB_WAITFD_PRI POLLPRI

=end

Updated by edelsohn (David Edelsohn) about 11 years ago

I do not know why the documentation page that you referenced does not mention "events". The same header also exists in AIX 6.1, and probably earlier. It may have been removed in some update, but that does not address existing systems.

Ruby thread.c uses revents:

if (fds.revents & POLLIN_SET)
    result |= RB_WAITFD_IN;
if (fds.revents & POLLOUT_SET)
    result |= RB_WAITFD_OUT;
if (fds.revents & POLLEX_SET)
    result |= RB_WAITFD_PRI;

so your patch causes the statements to refer to the wrong members. It seems safer to #undef the offending macro instead of defining more macros. Wrapping it in #ifdef _AIX is fine.

diff --git i/include/ruby/io.h w/include/ruby/io.h
index 07be55c..12ffc76 100644
--- i/include/ruby/io.h
+++ w/include/ruby/io.h
@@ -29,6 +29,9 @@ extern "C" {

#include "ruby/config.h"
#if defined(HAVE_POLL)
+# ifdef _AIX
+# undef events
+# endif

include <poll.h>

define RB_WAITFD_IN POLLIN

define RB_WAITFD_PRI POLLPRI

Actions #3

Updated by edelsohn (David Edelsohn) about 11 years ago

Unfortunately this fix no longer will work with Ruby trunk because thread_pthread.c added references to "events":

pollfds[0].fd = timer_thread_pipe[0];
pollfds[0].events = POLLIN;
pollfds[1].fd = timer_thread_pipe_low[0];
pollfds[1].events = POLLIN;

Updated by kosaki (Motohiro KOSAKI) about 11 years ago

So, I suspect AIX need to undefine HAVE_POLL. i.e. need some configure.in magic.

Updated by nobu (Nobuyoshi Nakada) about 11 years ago

=begin
I could reproduce the error by copying system ((%sys/poll.h%)) header to
((%include/poll.h%)) with editing like the AIX header. And by adding these
two lines just before (({#include <poll.h>})) line in ((%include/ruby/io.h%)), it
builds fine.

define reqevents events

define rtnevents revents

=end

Updated by edelsohn (David Edelsohn) about 11 years ago

Sorry Nakada-san. I misinterpreted your proposed fix. Yes, inserting those definitions before including poll.h allows thread.c to compile successfully.

Actions #7

Updated by nobu (Nobuyoshi Nakada) about 11 years ago

  • Status changed from Feedback to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r39987.
David, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


ruby/io.h: get rid of conflict on AIX

  • include/ruby/io.h: rename SVR3,4 member names as POSIX compliants,
    to get rid of conflict on AIX. [ruby-core:53765] [Bug #8174]
Actions #8

Updated by nobu (Nobuyoshi Nakada) about 11 years ago

  • Tracker changed from Bug to Backport
  • Project changed from Ruby master to Backport200
  • Status changed from Closed to Assigned
  • Assignee set to nagachika (Tomoyuki Chikanaga)

Updated by edelsohn (David Edelsohn) about 11 years ago

Nakada-san, The patch checked in to ruby-trunk was not the same as the one that you proposed. The patch #undefs the macros after including poll.h.

ifdef _AIX

define reqevents events

define rtnevents revents

endif

include <poll.h>

ifdef _AIX

undef reqevents

undef rtnevents

endif

With changeset r39987, AIX remains broken.

Your original patch redefined the identifiers throughout the entire file. The committed patch exchanges some names within poll.h but does not satisfy identifiers used within thread.c

With the original proposed patch, thread.i looks like:

struct pollfd
{
long fd;
ushort events;
ushort revents;
};
#define events reqevents
#define revents rtnevents

pollfds[0].fd = timer_thread_pipe[0];
pollfds[0].events = 0x0001;
pollfds[1].fd = timer_thread_pipe_low[0];
pollfds[1].events = 0x0001;

do { rb_thread_t * const _th = (th); struct rb_vm_tag _tag; _tag.tag = 0; _tag.
prev = _th->tag; _th->tag = &_tag;;
if ((state = _setjmp(_th->tag->buf)) == 0) {
do if (_setjmp((th)->root_jmpbuf) == 0) { { if (!th->first_func) { do { ((p
roc)) = (rb_proc_t*)(((struct RData*)((th->first_proc)))->data); } while (0); th
->errinfo = ((VALUE)RUBY_Qnil); th->root_lep = rb_vm_ep_local_ep(proc->block.ep)
; th->root_svar = ((VALUE)RUBY_Qnil); do { if ((builtin_expect((ruby_vm_event
flags & (0x0400)), 0))) { if (((th)->event_hooks.events | (th)->vm->event_hooks.
events) & (0x0400)) { struct rb_trace_arg_struct trace_arg; trace_arg.event = (0
x0400); trace_arg.th = (th); trace_arg.cfp = (trace_arg.th)->cfp; trace_arg.self
= (th->self); trace_arg.id = (0); trace_arg.klass = (0); trace_arg.data = (((VA
LUE)RUBY_Qundef)); trace_arg.path = ((VALUE)RUBY_Qundef); trace_arg.klass_solved
= 0; if (0) rb_threadptr_exec_event_hooks_and_pop_frame(&trace_arg); else rb_th
readptr_exec_event_hooks(&trace_arg); } } } while (0); th->value = rb_vm_invoke

proc(th, proc, (int)((((struct RBasic*)(args))->flags & (((VALUE)1)<<(12 +1))) ?
(long)((((struct RBasic*)(args))->flags >> (12 +3)) & (((((VALUE)1)<<(12 +4))|(
((VALUE)1)<<(12 +3))) >> (12 +3))) : ((struct RArray*)(args))->as.heap.len), (((
(struct RBasic*)(args))->flags & (((VALUE)1)<<(12 +1))) ? ((struct RArray*)(args
))->as.ary : ((struct RArray*)(args))->as.heap.ptr), 0); do { if ((__builtin_exp
ect((ruby_vm_event_flags & (0x0800)), 0))) { if (((th)->event_hooks.events | (th
)->vm->event_hooks.events) & (0x0800)) { struct rb_trace_arg_struct trace_arg; t
race_arg.event = (0x0800); trace_arg.th = (th); trace_arg.cfp = (trace_arg.th)->
cfp; trace_arg.self = (th->self); trace_arg.id = (0); trace_arg.klass = (0); tra
ce_arg.data = (((VALUE)RUBY_Qundef)); trace_arg.path = ((VALUE)RUBY_Qundef); tra
ce_arg.klass_solved = 0; if (0) rb_threadptr_exec_event_hooks_and_pop_frame(&tra
ce_arg); else rb_threadptr_exec_event_hooks(&trace_arg); } } } while (0); } else
{ th->value = (*th->first_func)((void *)args); } }; } else { rb_fiber_start();
} while (0)

because the pollfd struct declaration is affected in the header to use the correct member names directly.

With the current sources, the pollfd struct declaration is modifier, but the rest of the file uses the wrong member names:

struct pollfd
{
long fd;
ushort events;
ushort revents;
};
#define events reqevents
#define revents rtnevents

#undef reqevents
#undef rtnevents

pollfds[0].fd = timer_thread_pipe[0];
pollfds[0].reqevents = 0x0001;
pollfds[1].fd = timer_thread_pipe_low[0];
pollfds[1].reqevents = 0x0001;

if ((state = _setjmp(_th->tag->buf)) == 0) {
do if (_setjmp((th)->root_jmpbuf) == 0) { { if (!th->first_func) { do { ((p
roc)) = (rb_proc_t*)(((struct RData*)((th->first_proc)))->data); } while (0); th
->errinfo = ((VALUE)RUBY_Qnil); th->root_lep = rb_vm_ep_local_ep(proc->block.ep)
; th->root_svar = ((VALUE)RUBY_Qnil); do { if ((builtin_expect((ruby_vm_event
flags & (0x0400)), 0))) { if (((th)->event_hooks.reqevents | (th)->vm->event_hoo
ks.reqevents) & (0x0400)) { struct rb_trace_arg_struct trace_arg; trace_arg.even
t = (0x0400); trace_arg.th = (th); trace_arg.cfp = (trace_arg.th)->cfp; trace_ar
g.self = (th->self); trace_arg.id = (0); trace_arg.klass = (0); trace_arg.data =
(((VALUE)RUBY_Qundef)); trace_arg.path = ((VALUE)RUBY_Qundef); trace_arg.klass

solved = 0; if (0) rb_threadptr_exec_event_hooks_and_pop_frame(&trace_arg); else
rb_threadptr_exec_event_hooks(&trace_arg); } } } while (0); th->value = rb_vm_i
nvoke_proc(th, proc, (int)((((struct RBasic*)(args))->flags & (((VALUE)1)<<(12 +
1))) ? (long)((((struct RBasic*)(args))->flags >> (12 +3)) & (((((VALUE)1)<<(12
+4))|(((VALUE)1)<<(12 +3))) >> (12 +3))) : ((struct RArray*)(args))->as.heap.len
), ((((struct RBasic*)(args))->flags & (((VALUE)1)<<(12 +1))) ? ((struct RArray*
)(args))->as.ary : ((struct RArray*)(args))->as.heap.ptr), 0); do { if ((_built
in_expect((ruby_vm_event_flags & (0x0800)), 0))) { if (((th)->event_hooks.reqeve
nts | (th)->vm->event_hooks.reqevents) & (0x0800)) { struct rb_trace_arg_struct
trace_arg; trace_arg.event = (0x0800); trace_arg.th = (th); trace_arg.cfp = (tra
ce_arg.th)->cfp; trace_arg.self = (th->self); trace_arg.id = (0); trace_arg.klas
s = (0); trace_arg.data = (((VALUE)RUBY_Qundef)); trace_arg.path = ((VALUE)RUBY

Qundef); trace_arg.klass_solved = 0; if (0) rb_threadptr_exec_event_hooks_and_po
p_frame(&trace_arg); else rb_threadptr_exec_event_hooks(&trace_arg); } } } while
(0); } else { th->value = (*th->first_func)((void *)args); } }; } else { rb_fib
er_start(); } while (0)

and there is no member reqevents in struct pollfd.

Updated by edelsohn (David Edelsohn) about 11 years ago

Let me explain it this way:

Either io.h needs to leave the macro definitions for _AIX defined,

OR io.h needs to undefine both the macro definitions that it created for _AIX and the macro definitions that the AIX sys/poll.h header defined.

Actions #11

Updated by nobu (Nobuyoshi Nakada) about 11 years ago

  • Tracker changed from Backport to Bug
  • Project changed from Backport200 to Ruby master
  • Assignee changed from nagachika (Tomoyuki Chikanaga) to nobu (Nobuyoshi Nakada)

Updated by nobu (Nobuyoshi Nakada) about 11 years ago

  • % Done changed from 100 to 50
  • ruby -v set to trunk
Actions #13

Updated by nobu (Nobuyoshi Nakada) about 11 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 50 to 100

This issue was solved with changeset r39993.
David, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


ruby/io.h: get rid of conflict on AIX

  • include/ruby/io.h: undef POSIX compliants names on AIX, which are no
    longer needed. patch suggested by edelsohn (David Edelsohn) in
    [ruby-core:53815]. [Bug #8174]
Actions #14

Updated by nobu (Nobuyoshi Nakada) about 11 years ago

  • Tracker changed from Bug to Backport
  • Project changed from Ruby master to Backport200
  • Status changed from Closed to Assigned
  • Assignee changed from nobu (Nobuyoshi Nakada) to nagachika (Tomoyuki Chikanaga)

Updated by edelsohn (David Edelsohn) about 11 years ago

Thank you, Nakada-san. ruby-trunk now builds on AIX. Testing only reports one error.

Who can I contact to set up buildbot CI testers and connect them to the testing infrastructure, such as rubyci.org?

Actions #16

Updated by nagachika (Tomoyuki Chikanaga) about 11 years ago

  • Status changed from Assigned to Closed

This issue was solved with changeset r40292.
David, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


merge revision(s) 39987,39993,39998: [Backport #8174]

* include/ruby/io.h: rename SVR3,4 member names as POSIX compliants,
  to get rid of conflict on AIX.  [ruby-core:53765] [Bug #8174]

* include/ruby/io.h: undef POSIX compliants names on AIX, which are no
  longer needed.  patch suggested by edelsohn (David Edelsohn) in
  [ruby-core:53815].  [Bug #8174]

* include/ruby/io.h: undef POSIX compliant names on AIX, which are no

* include/ruby/io.h: rename SVR3,4 member names as POSIX compliant,
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0