The Pth 1.4.1 "Hard System Call Mapping" scheme makes use of the syscall(2)
function to wrap system calls.  The Pth doc acknowledges that this may
hit conflicts with the vendor's header files, but there is another more 
fundamental problem as well:

This approach assumes that the C library interface for a function is the
same as its underlying syscall() interface, in terms of arguments and
return values.  In most cases this is true, but for some calls on some
OSes it is not.  For example on SCO's UnixWare/Open UNIX OS, both
system() and waitpid() have a system call interface that uses multiple
return values via assembly language registers. These return values are
mapped to the POSIX signature by an assembly code layer within the C library.  
Consequently, calling these functions in the C library and calling them via 
syscall() do not produce the same results; you simply can't use syscall() for 
them from application C code.  Thus, the Pth hard wrapper mechanism breaks 
down.

An alternative approach is to use the dlsym(RTLD_NEXT) feature, which
is specified in the Unix 98 standard and is available on many current-day
systems.  This is a more robust way of coding wrapper functions for 
system calls, since it's designed for that purpose.  Note that for this
to work you have to use the dynamically linked Pth libpthread, so that the
"real" definition can be found in a downstream library (usually libc).

Here are the changes to use dlsym.  They are to pth_lib.c and pth_syscall.c.
The changes are mostly in one place, due to good encapsulation provided by
the pth_sc macro.

--- pth_lib.c..orig     Sun Jan 27 06:03:40 2002
+++ pth_lib.c   Tue Oct 15 13:15:04 2002
@@ -47,6 +47,11 @@
 int pth_init(void)
 {
     pth_attr_t t_attr;
+#if defined(__USLC__) || defined(__svr4__)
+#if PTH_SYSCALL_HARD
+    extern int pth_sys_func_table_init(void);
+#endif
+#endif
 
     /* support for implicit initialization calls
        and to prevent multiple explict initialization, too */
@@ -55,6 +60,13 @@
     else
         pth_initialized = TRUE;
 
+#if defined(__USLC__) || defined(__svr4__)
+#if PTH_SYSCALL_HARD
+    if (pth_sys_func_table_init() == FALSE)
+       return FALSE;
+#endif
+#endif
+
     pth_debug1("pth_init: enter");
 
     /* initialize the scheduler */



--- pth_syscall.c..orig Sun Jan 27 06:03:41 2002
+++ pth_syscall.c       Tue Oct 15 11:58:31 2002
@@ -36,13 +36,78 @@
 #ifdef HAVE_SYS_SOCKETCALL_H
 #include <sys/socketcall.h>
 #endif
+#if defined(__USLC__) || defined(__svr4__)
+int pth_sys_func_table_init(void);
+typedef int (*pth_sys_func_t)();
+typedef struct pth_sys_func_table_t {
+    char* name;
+    pth_sys_func_t addr;
+} pth_sys_func_table_t;
+extern pth_sys_func_table_t pth_sys_func_table[];
+#define PTH_SFT_read 0
+#define PTH_SFT_readv 1
+#define PTH_SFT_write 2
+#define PTH_SFT_writev 3
+#define PTH_SFT_select 4
+#define PTH_SFT_connect 5
+#define PTH_SFT_accept 6
+#define PTH_SFT_recvfrom 7
+#define PTH_SFT_sendto 8
+#define PTH_SFT_fork 9
+#define PTH_SFT_sigprocmask 10
+#define PTH_SFT_waitpid 11
+#define PTH_SFT__xconnect 12
+#define PTH_SFT__xaccept 13
+#define PTH_SFT__xrecvfrom 14
+#define PTH_SFT__xsendto 15
+#define pth_sc(func) (*pth_sys_func_table[PTH_SFT_##func].addr)
+#else
 #define pth_sc(func) PTH_SC_##func
+#endif
 #else
 #define pth_sc(func) func
 #endif
 
 #endif /* cpp */
 
+#if defined(__USLC__) || defined(__svr4__)
+#if PTH_SYSCALL_HARD
+#include <dlfcn.h>
+
+pth_sys_func_table_t pth_sys_func_table[] = {
+       // this order must match the macro values above
+       { "read", NULL },
+       { "readv", NULL },
+       { "write", NULL },
+       { "writev", NULL },
+       { "select", NULL },
+       { "connect", NULL },
+       { "accept", NULL },
+       { "recvfrom", NULL },
+       { "sendto", NULL },
+       { "fork", NULL },
+       { "sigprocmask", NULL },
+       { "waitpid", NULL },
+       { "_xconnect", NULL },
+       { "_xaccept", NULL },
+       { "_xrecvfrom", NULL },
+       { "_xsendto", NULL },
+       { NULL, NULL },
+};
+
+int pth_sys_func_table_init(void) {
+    pth_sys_func_table_t* p_sft = pth_sys_func_table;
+    while (p_sft->name != NULL) {
+       p_sft->addr = (pth_sys_func_t) dlsym(RTLD_NEXT, p_sft->name);
+       // Note the above dlsym() may return NULL, 
+       //  e.g. the networking calls when libsocket is not linked.
+       p_sft++;
+    }     
+    return TRUE;
+}
+#endif
+#endif
+
 /* some exported variables for object layer checks */
 int pth_syscall_soft = PTH_SYSCALL_SOFT;
 int pth_syscall_hard = PTH_SYSCALL_HARD;


The "defined(__USLC__) || defined(__svr4__)" test is to activate it for
SCO UNIX systems; if this were to be incorporated in mainline Pth, this 
would have to be replaced with a macro test driven from the configure 
process, since the syscall() method needs to be retained as an option for 
systems that don't have dlsym(RTLD_NEXT) and for static links.


Jonathan Schilling              SCO/Caldera             [EMAIL PROTECTED]
______________________________________________________________________
GNU Portable Threads (Pth)            http://www.gnu.org/software/pth/
User Support Mailing List                            [EMAIL PROTECTED]
Automated List Manager (Majordomo)           [EMAIL PROTECTED]

Reply via email to