Re: Problem Calling "kill" in threaded 64-bit MF Server Express 4.0 SP2



Thanks Michael.

The reasoning behind the behvaior definitely makes sense. Being new to
the threaded environment, I expect there will be more issue like this
for me to deal with - but thankfully so far things have gone well.

The sample code I posted above works perfectly, and I believe it
reflects exactly what you were going for. What do you think of it?


BTW - for all of those folks who post here doubting the fact that
Michael does in fact work for Micro Focus :) - I can vouch for him. He
is most definitely a MF employee, and I had the pleasure of meeting him
at the Developer's Forum in Denver a couple of weeks ago.


Chris



Michael Wojcik wrote:
In article <1143604712.201547.254640@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>, "Chris" <ctaliercio@xxxxxxxxx> writes:

I have the following snippet of code:


77 int pic s9(09) comp-5 is typedef.
77 u-int pic 9(9) comp-5 is typedef.

77 errno u-int external.


01 my-pid int.
01 rc int.


MOVE <some value> TO my-pid

CALL "kill" USING
BY VALUE my-pid
BY VALUE 0
RETURNING
rc
END-CALL



Now for the fun part. In a non-threaded runtime (rts64), when I move
the value of a PID that I am not the owner of to my-pid, I get the
following results:

rc=-1
errno=1

errno=1 indicates the UNIX EPERM error, which is what I expect. The
process exists and I do not have permissions on it.


In the threaded (rts64_t) runtime, when I execute the same snip of
code, I get the following results:

rc=-1
errno=25

That's because in a threaded environment, errno is not a single global
integer. Each thread needs its own errno to preserve the errno
semantics.

Since ISO C requires that errno be an expression that evaluates to an
int lvalue (that is, an object of int type that you can modify), the
usual (perhaps only) approach in Unix multithreaded C implementations
is to make errno a macro that expands to a dereferencing of a pointer
returned by a function call. If you track down the appropriate header
file, you'll probably see something like this:

extern int *_thread_errno(void);
#define errno (*_thread_errno());

So when you refer to errno in a multithreaded C program in this
implementation, what actually happens is a function call that returns
a pointer to the errno area for the current thread; then that pointer
is dereferenced so you can retrieve and set the value contained in
that area.

System calls which set errno, in turn, have to use the same
mechanism, since they're used by multithreaded C programs.

There may still be an external variable named "errno", but its value
doesn't mean anything. It may be garbage, or it may contain the most
recent errno value set for any thread; that depends on the implementa-
tion, and you can't rely on it.

I'm not sure there's a good, simple method to get the per-thread
errno in a multithreaded COBOL program. One approach would be to
write a small C routine to return it:

#include <errno.h>
int geterrno(void) {return errno;}

and compile that into a CSO:

$ cob -t -z -CC -D_REENTRANT geterrno.c

and call it to get errno in your COBOL program:

identification division.
program-id. testerrno.

data division.
working-storage section.
77 my-errno pic s9(9) comp-5.
77 rc pic s9(9) comp-5.

procedure division.

call "kill" using by value 1 0 returning rc.
call "geterrno" returning my-errno.
exhibit rc my-errno.
stop run.

To test:

$ cob -t -i testerrno.cbl
$ rts64_t testerrno
-0000000001 +0000000001

I just tried this on an HP-UX 11i system, and it seems to work fine.
Note that it's crucial that your geterrno.c program be compiled in
the same mode (single- or multithreaded) as your COBOL program for
this to work, so you might want single- and multithreaded versions
of it (with different names). Also, the way to get a C program
compiled for multithreading depends on the implementation - the
command line I have above works with the HP-UX ANSI C compiler.

(Also, errno is an int, not an unsigned int. If you happen to be on
a 64-bit platform where int is 64 bits, it'll be a 64-bit int. The
first parameter to the kill system call is a pid_t, which is an
implementation-dependent type; it too could be a 64-bit integer type.
On HP-UX 11i, though, they're both 32-bit integers, and signedness
won't matter.)

--
Michael Wojcik michael.wojcik@xxxxxxxxxxxxxx

Auden often writes like Disney. Like Disney, he knows the shape of beasts --
(& incidently he, too, might have a company of artists producing his lines) --
unlike Lawrence, he does not know what shapes or motivates these beasts.
-- Dylan Thomas

.



Relevant Pages