Backport #8174

AIX header file conflict with rb_hook_list_struct

Added by David Edelsohn about 1 year ago. Updated about 1 year ago.

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

Description

=begin
rbhooklist_struct defines a member "events":

typedef struct rbhookliststruct {
struct rb
eventhookstruct *hooks;
rbeventflagt events;
int need
clean;
} rbhooklist_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 EXECEVENTHOOK, 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 'threadstartfunc2':
/usr/gnu/src/ruby-2.0.0-p0/thread.c:496:6: error: 'rb
hooklistt' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c:496:6: error: 'rbhooklistt' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c:496:6: error: 'rb
hooklistt' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c:496:6: error: 'rbhooklistt' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c: In function 'rb
threadptrexecuteinterrupts':
/usr/gnu/src/ruby-2.0.0-p0/thread.c:1917:6: error: 'rbhooklistt' has no member named 'reqevents'
/usr/gnu/src/ruby-2.0.0-p0/thread.c:1917:6: error: 'rb
hooklistt' 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(HAVEPOLL)
# include
+# undef events
# define RB
WAITFDIN POLLIN
# define RB
WAITFDPRI POLLPRI
# define RB
WAITFD_OUT POLLOUT
=end

Associated revisions

Revision 40292
Added by Tomoyuki Chikanaga about 1 year 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 about 1 year 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(HAVEPOLL)
+# ifdef _AIX
+# define reqevents events
+# define rtnevents revents
+# endif
# include
# define RB
WAITFDIN POLLIN
# define RB
WAITFD_PRI POLLPRI
=end

#2 Updated by David Edelsohn about 1 year 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(HAVEPOLL)
+# ifdef _AIX
+# undef events
+# endif
# include
# define RB
WAITFDIN POLLIN
# define RB
WAITFD_PRI POLLPRI

#3 Updated by David Edelsohn about 1 year 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 about 1 year ago

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

#5 Updated by Nobuyoshi Nakada about 1 year 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 about 1 year 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 about 1 year 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. [Bug #8174]

#8 Updated by Nobuyoshi Nakada about 1 year ago

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

#9 Updated by David Edelsohn about 1 year 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 { rbthreadt * const th = (th); struct rbvmtag _tag; _tag.tag = 0; _tag.
prev = _th->tag; _th->tag = &
tag;;
if ((state = setjmp(th->tag->buf)) == 0) {
do if (setjmp((th)->rootjmpbuf) == 0) { { if (!th->firstfunc) { do { ((p
roc)) = (rb
proct)(((struct RData)((th->firstproc)))->data); } while (0); th
->errinfo = ((VALUE)RUBYQnil); th->rootlep = rbvmeplocalep(proc->block.ep)
; th->rootsvar = ((VALUE)RUBYQnil); do { if ((builtinexpect((rubyvmevent
flags & (0x0400)), 0))) { if (((th)->eventhooks.events | (th)->vm->eventhooks.
events) & (0x0400)) { struct rbtraceargstruct tracearg; tracearg.event = (0
x0400); trace
arg.th = (th); tracearg.cfp = (tracearg.th)->cfp; tracearg.self
= (th->self); trace
arg.id = (0); tracearg.klass = (0); tracearg.data = (((VA
LUE)RUBYQundef)); tracearg.path = ((VALUE)RUBYQundef); tracearg.klasssolved
= 0; if (0) rb
threadptrexeceventhooksandpopframe(&tracearg); else rbth
readptrexeceventhooks(&tracearg); } } } while (0); th->value = rbvminvoke_
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 ((
builtinexp
ect((ruby
vmeventflags & (0x0800)), 0))) { if (((th)->eventhooks.events | (th
)->vm->event
hooks.events) & (0x0800)) { struct rbtraceargstruct tracearg; t
racearg.event = (0x0800); tracearg.th = (th); tracearg.cfp = (tracearg.th)->
cfp; tracearg.self = (th->self); tracearg.id = (0); tracearg.klass = (0); tra
ce
arg.data = (((VALUE)RUBYQundef)); tracearg.path = ((VALUE)RUBYQundef); tra
ce
arg.klasssolved = 0; if (0) rbthreadptrexeceventhooksandpopframe(&tra
cearg); else rbthreadptrexeceventhooks(&tracearg); } } } while (0); } else
{ th->value = (*th->firstfunc)((void *)args); } }; } else { rbfiber_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)->rootjmpbuf) == 0) { { if (!th->firstfunc) { do { ((p
roc)) = (rb
proct)(((struct RData)((th->firstproc)))->data); } while (0); th
->errinfo = ((VALUE)RUBYQnil); th->rootlep = rbvmeplocalep(proc->block.ep)
; th->rootsvar = ((VALUE)RUBYQnil); do { if ((builtinexpect((rubyvmevent
flags & (0x0400)), 0))) { if (((th)->eventhooks.reqevents | (th)->vm->eventhoo
ks.reqevents) & (0x0400)) { struct rbtraceargstruct tracearg; tracearg.even
t = (0x0400); trace
arg.th = (th); tracearg.cfp = (tracearg.th)->cfp; tracear
g.self = (th->self); trace
arg.id = (0); tracearg.klass = (0); tracearg.data =
(((VALUE)RUBYQundef)); tracearg.path = ((VALUE)RUBYQundef); tracearg.klass_
solved = 0; if (0) rbthreadptrexeceventhooksandpopframe(&tracearg); else
rbthreadptrexeceventhooks(&tracearg); } } } while (0); th->value = rbvmi
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
inexpect((rubyvmeventflags & (0x0800)), 0))) { if (((th)->eventhooks.reqeve
nts | (th)->vm->event
hooks.reqevents) & (0x0800)) { struct rbtraceargstruct
trace
arg; tracearg.event = (0x0800); tracearg.th = (th); tracearg.cfp = (tra
ce
arg.th)->cfp; tracearg.self = (th->self); tracearg.id = (0); tracearg.klas
s = (0); trace
arg.data = (((VALUE)RUBYQundef)); tracearg.path = ((VALUE)RUBY_
Qundef); tracearg.klasssolved = 0; if (0) rbthreadptrexeceventhooksandpo
pframe(&tracearg); else rbthreadptrexeceventhooks(&tracearg); } } } while
(0); } else { th->value = (*th->first
func)((void *)args); } }; } else { rbfib
er
start(); } while (0)

and there is no member reqevents in struct pollfd.

#10 Updated by David Edelsohn about 1 year 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 about 1 year ago

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

#12 Updated by Nobuyoshi Nakada about 1 year ago

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

#13 Updated by Nobuyoshi Nakada about 1 year 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 . [Bug #8174]

#14 Updated by Nobuyoshi Nakada about 1 year ago

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

#15 Updated by David Edelsohn about 1 year 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 1 year 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