Backport #8174

AIX header file conflict with rb_hook_list_struct

Added by David Edelsohn over 2 years ago. Updated about 2 years ago.

[ruby-core:53765]
Status:Closed
Priority:Normal
Assignee:Tomoyuki Chikanaga

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
+# undef events
# define RB_WAITFD_IN POLLIN
# define RB_WAITFD_PRI POLLPRI
# define RB_WAITFD_OUT POLLOUT
=end

Associated revisions

Revision 39987
Added by Nobuyoshi Nakada over 2 years ago

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. [Bug #8174]

Revision 39993
Added by Nobuyoshi Nakada over 2 years ago

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 . [Bug #8174]

Revision 40292
Added by Tomoyuki Chikanaga about 2 years ago

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.   [Bug #8174]

* include/ruby/io.h: undef POSIX compliants names on AIX, which are no
  longer needed.  patch suggested by edelsohn (David Edelsohn) in
  .  [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,

History

#1 Updated by Nobuyoshi Nakada over 2 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
# define RB
WAITFD_IN POLLIN
# define RB_WAITFD_PRI POLLPRI
=end

#2 Updated by David Edelsohn over 2 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
# define RB
WAITFD_IN POLLIN
# define RB_WAITFD_PRI POLLPRI

#3 Updated by David Edelsohn over 2 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;

#4 Updated by Motohiro KOSAKI over 2 years ago

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

#5 Updated by Nobuyoshi Nakada over 2 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 })) line in ((%include/ruby/io.h%)), it
builds fine.

# define reqevents events
# define rtnevents revents
=end

#6 Updated by David Edelsohn over 2 years ago

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

#7 Updated by Nobuyoshi Nakada over 2 years ago

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

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. [Bug #8174]

#8 Updated by Nobuyoshi Nakada over 2 years ago

  • Tracker changed from Bug to Backport
  • Project changed from Ruby trunk to Backport200
  • Assignee set to Tomoyuki Chikanaga
  • Status changed from Closed to Assigned

#9 Updated by David Edelsohn over 2 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

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.

#10 Updated by David Edelsohn over 2 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.

#11 Updated by Nobuyoshi Nakada over 2 years ago

  • Tracker changed from Backport to Bug
  • Assignee changed from Tomoyuki Chikanaga to Nobuyoshi Nakada
  • Project changed from Backport200 to Ruby trunk

#12 Updated by Nobuyoshi Nakada over 2 years ago

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

#13 Updated by Nobuyoshi Nakada over 2 years ago

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

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 . [Bug #8174]

#14 Updated by Nobuyoshi Nakada over 2 years ago

  • Tracker changed from Bug to Backport
  • Status changed from Closed to Assigned
  • Assignee changed from Nobuyoshi Nakada to Tomoyuki Chikanaga
  • Project changed from Ruby trunk to Backport200

#15 Updated by David Edelsohn over 2 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?

#16 Updated by Tomoyuki Chikanaga about 2 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.   [Bug #8174]

* include/ruby/io.h: undef POSIX compliants names on AIX, which are no
  longer needed.  patch suggested by edelsohn (David Edelsohn) in
  .  [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,

Also available in: Atom PDF