[net.unix-wizards] Microport Unix -- Large Model Problems

ron@vsedev.VSE.COM (Ron Flax) (10/29/86)

Has anyone  else  out  there  been  experiencing  problems  with porting
programs to Microport Unix V/AT that fall into the large model category?
It seems  that  most  everything  I  port  (try  to port?)   has pointer
alignment problems,  as  indicated by  lint, or  just core  dumps with a
segmentation violation at strange places in the code, like on a strlen()
call?

Sdb seems to indicate a  memory fault  as the  culprit and  I think that
most of the problems are pointer related since an 'int' ain't
necessarily an 'int'  (ie.   16 bits  in small  model, 32  bits in large
model).  Does anyone have any  words of  wisdom as  to how  one might go
about fixing pointer alignment problems without too much pain?

One other unrelated problem I have with Microport  Unix is  that for one
reason or  another  the system  seems to  run for  a while  then when it
decides its had enough it just  plain goes  south.   It appears  to be a
deadlock situation  since  terminals  that  had  active  sessions  going
continue to echo keystroke even  though it  doesn't respond  to them and
non-active sessions (ie.  getty's running) do NOT echo keystrokes.  This
obviously quite annoying as you might imagine...   One  other thing that
is interesting is that I  know of  two other  sites with  the exact same
problem on  different  hardware,  but  Microport claims  they have never
heard of it?  Has anyone else  seen this  behavior?   Incidentally I was
running SCO Xenix  V successfully  for about  6 months  prior to getting
Microport Unix.  Microport are you listening 8-)

--
ron@vsedev.VSE.COM	(Ron Flax)
UUCP:	..!seismo!vsedev!ron
ARPA:	vsedev.VSE.COM!ron@seismo.CSS.GOV

campbell@maynard.UUCP (Larry Campbell) (10/31/86)

In article <188@vsedev.VSE.COM> ron@vsedev.VSE.COM (Ron Flax) writes:
>Has anyone  else  out  there  been  experiencing  problems  with porting
>programs to Microport Unix V/AT that fall into the large model category?
>It seems  that  most  everything  I  port  (try  to port?)   has pointer
>alignment problems,  as  indicated by  lint, or  just core  dumps with a
>segmentation violation at strange places in the code, like on a strlen()
>call?
>
>Sdb seems to indicate a  memory fault  as the  culprit and  I think that
>most of the problems are pointer related since an 'int' ain't
>necessarily an 'int'  (ie.   16 bits  in small  model, 32  bits in large
>model).  Does anyone have any  words of  wisdom as  to how  one might go
>about fixing pointer alignment problems without too much pain?

The simplest solution is to get your code to pass through lint without
complaints.  The most common problem I've found (especially from code
written on 68Ks and VAXen) is for people to not bother declaring pointer
valued objects:

	char *p;

	p = malloc(128);

oops, malloc is implicitly declared (int), not (char *), so you get
a bogus pointer because ints are 16 bits while pointers are 32 bits.
There should have been an "extern char *malloc();" in there.  Lint will
find these for you.
-- 
Larry Campbell       MCI: LCAMPBELL          The Boston Software Works, Inc.
UUCP: {alliant,wjh12}!maynard!campbell      120 Fulton Street, Boston MA 02109
ARPA: campbell%maynard.uucp@harvisr.harvard.edu     (617) 367-6846

dan@prairie.UUCP (Daniel M. Frank) (10/31/86)

In article <188@vsedev.VSE.COM> ron@vsedev.VSE.COM (Ron Flax) writes:
>Has anyone  else  out  there  been  experiencing  problems  with porting
>programs to Microport Unix V/AT that fall into the large model category?
>It seems  that  most  everything  I  port  (try  to port?)   has pointer
>alignment problems,  as  indicated by  lint, or  just core  dumps with a
>segmentation violation at strange places in the code, like on a strlen()
>call?

   The problems aren't generally with Microport, they are with brain-
damaged, unlinted programs that presume that sizeof int = sizeof *,
or even (in one case), that ALL scalar data types are always the same
size when passed into a function.  Let me make a few observations and
suggestions of how to find these problems and what to watch for.

   First, the lint you have is probably broken, unless you have the
very latest release (in the last two days).  You will find the new,
repaired version of lint (and sdb, actually), very useful.

   Suggestion:  compile everything with -g.  sdb is very useful
for finding obscure portability bugs that lint will not find (usually
because of a VARARGS directive).

   Nasties to watch for:

    1) Failure to declare functions returning long or *.  The compiler
	   will happily truncate return values to one word, which will
	   usually cause segmentation violations very quickly, or in
	   the case of long returns, cause odd program behaviour.  malloc()
	   and time() are favorites, as are string functions returning
	   pointers.

	2) Constructs of the form 1 << n, where n is greater than 15.
	   Guess what happens?  The compiler optimizes this to zeroing
	   out a register.  You want 1L << n.  This bug is from compress.c

	3) Silly function arguments, usually constants.  time(0) is a
	   popular one.  This should be time((long *)0).

	4) Very silly constant function arguments in varargs functions,
	   where lint can't find them.  execl and execle are very
	   popular in this category.  Watch for varargs functions
	   that use null pointers to terminate lists; folks usually
	   use 0 rather than the proper (char *)0.

	5) Varargs functions that use a bunch of integer arguments
	   to copy the stack.  These are all over the place, in
	   such classics as patch and inews.  The method is not
	   bad, per se, but usually there aren't enough of these
	   arguments if ints are shorter than pointers.  Redeclare
	   them to be long instead.


   (I am posting this generally, rather than mailing back to the poster,
because I would beg, implore, plead, and otherwise abase myself before
authors of C programs posted to the net to try and be sensitive to
some of these problems.  Yes, I know the 286 is brain-damaged and all
that, but a bunch of us got `em cheap from this guy in a plaid sport
coat who told us that they were the wave of the future, and now we
can't afford Suns.  Watch for assumptions about pointer sizes.  Use
the varargs functions and macros provided in System V and BSD instead
of bogus argument lists.)

   On the crash problem, try again with Microport support.  Stress
that there are not many multi-terminal sites, and that this is occurring
on different hardware.  Ask for Henry and use my name.

   Good luck!
	  Dan

-- 
    Dan Frank
    uucp: ... uwvax!prairie!dan
    arpa: dan%caseus@spool.wisc.edu

campbell@maynard.UUCP (Larry Campbell) (11/01/86)

In article <271@prairie.UUCP> dan@prairie.UUCP (Daniel M. Frank) writes:
>...On the crash problem, try again with Microport support.  Stress
>that there are not many multi-terminal sites, and that this is occurring
>on different hardware.  Ask for Henry and use my name.

Poor Henry...  he seems to be awfully busy these days.

- A more-or-less satisifed Microport customer (well, so far the hassles
  I've encountered haven't negated the $800 I saved by going Microport
  instead of Xenix) who has had the opportunity to chat with Henry on
  several occasions...
-- 
Larry Campbell       MCI: LCAMPBELL          The Boston Software Works, Inc.
UUCP: {alliant,wjh12}!maynard!campbell      120 Fulton Street, Boston MA 02109
ARPA: campbell%maynard.uucp@harvisr.harvard.edu     (617) 367-6846

dan@prairie.UUCP (Daniel M. Frank) (11/01/86)

In article <402@maynard.UUCP> campbell@maynard.UUCP (Larry Campbell) writes:
>Poor Henry...  he seems to be awfully busy these days.

   Actually, they just hired a roomfull of customer support people to help
him out.  He's still busy, though ...


-- 
    Dan Frank
    uucp: ... uwvax!prairie!dan
    arpa: dan%caseus@spool.wisc.edu

barber@rabbit1.UUCP (Steve Barber) (11/01/86)

In article <401@maynard.UUCP>, campbell@maynard.UUCP (Larry Campbell) writes:
> In article <188@vsedev.VSE.COM> ron@vsedev.VSE.COM (Ron Flax) writes:
> >Has anyone  else  out  there  been  experiencing  problems  with porting
> >programs to Microport Unix V/AT that fall into the large model category?

> ....  The most common problem I've found (especially from code
> written on 68Ks and VAXen) is for people to not bother declaring pointer
> valued objects:

Another common problem is passing NULL as pointer argument.  NULL is
#defined as 0, which is 2 bytes.  Large model pointers are 4 bytes, so
the stack frame is now basically garbage.  The solution is to cast the
NULLs to the appropriate types.  Ahhh..Intel..you can never be forgiven
for making us have to worry about memory models  (flames by mail only,
please).

-- 
Steve Barber    Rabbit Software Corp.
...!ihnp4!{cbmvax,cuuxb}!hutch!barber  ...!psuvax1!burdvax!hutch!barber
(215) 647-0440  7 Great Valley Parkway East  Malvern PA 19355

guy@sun.uucp (Guy Harris) (11/03/86)

> Another common problem is passing NULL as pointer argument.  NULL is
> #defined as 0, which is 2 bytes.  Large model pointers are 4 bytes, so
> the stack frame is now basically garbage.  The solution is to cast the
> NULLs to the appropriate types.  Ahhh..Intel..you can never be forgiven
> for making us have to worry about memory models...

Yes, having to worry about memory models may be a pain; however, even if you
didn't have multiple memory models, you'd *still* have to worry about
properly declaring pointer-valued functions and casting null pointers.  A
68K implementation might have 16-bit "int"s and 32-bit pointers, or might
return the value of an integral-type-valued function in D0 and the value of
a pointer-valued function in A0.  Other implementations might not use an
all-zero bit pattern to represent a null pointer.

I really hope that when the ANSI C standard comes out, compilers start
issuing warnings if you use a function that you haven't already declared, or
if you don't declare the types of the arguments to a function.  Yes, this
may inconvenience programmers, but the ones it most inconveniences are the
ones who just don't *care* about data types, and they're the ones who need
the biggest attitude adjustment.
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

dan@prairie.UUCP (Daniel M. Frank) (11/03/86)

In article <245@rabbit1.UUCP> barber@rabbit1.UUCP (Steve Barber) writes:
>Another common problem is passing NULL as pointer argument.  NULL is
>#defined as 0, which is 2 bytes.  Large model pointers are 4 bytes, so
>the stack frame is now basically garbage.

   This isn't really true.  Code in stdio.h for the SV/286 release
checks your memory model, and if it is large, defines NULL to be 0L,
which is the same size as a pointer.  It doesn't please lint, so the
best solution is still to cast it as appropriate (like (char *)0),
but you ARE generally safe, as long as you include stdio.h.


-- 
    Dan Frank
    uucp: ... uwvax!prairie!dan
    arpa: dan%caseus@spool.wisc.edu

campbell@maynard.UUCP (Larry Campbell) (11/04/86)

In article <347@prairie.UUCP> dan@prairie.UUCP (Daniel M. Frank) writes:
>In article <245@rabbit1.UUCP> barber@rabbit1.UUCP (Steve Barber) writes:
>>Another common problem is passing NULL as pointer argument.  NULL is
>>#defined as 0, which is 2 bytes.  Large model pointers are 4 bytes, so
>>the stack frame is now basically garbage.
>
>   This isn't really true.  Code in stdio.h for the SV/286 release
>checks your memory model, and if it is large, defines NULL to be 0L,
>which is the same size as a pointer.  It doesn't please lint, so the
>best solution is still to cast it as appropriate (like (char *)0),
>but you ARE generally safe, as long as you include stdio.h.

I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or,
in the brave new world of ANSI X-whatever, "(void *) 0"?  This should
do all the right things.
-- 
Larry Campbell       MCI: LCAMPBELL          The Boston Software Works, Inc.
UUCP: {alliant,wjh12}!maynard!campbell      120 Fulton Street, Boston MA 02109
ARPA: campbell%maynard.uucp@harvisr.harvard.edu     (617) 367-6846

garry@batcomputer.TN.CORNELL.EDU (Garry Wiegand) (11/04/86)

In a recent article campbell@maynard.UUCP (Larry Campbell) wrote:
>I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or,
>in the brave new world of ANSI X-whatever, "(void *) 0"?  This should
>do all the right things.

To get *all* the right things, we use:

	#ifdef	lint
	#   define	null	0
	#else
	#   define	null	(char *)0
	#endif

since lint doesn't understand that comparing an (int *) variable with a
(char *)0 is legitimate.

garry wiegand   (garry%cadif-oak@cu-arpa.cs.cornell.edu)

gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/04/86)

In article <405@maynard.UUCP> campbell@maynard.UUCP (Larry Campbell) writes:
>I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or,
>in the brave new world of ANSI X-whatever, "(void *) 0"?  This should
>do all the right things.

How quickly people forget.

In pre-X3J11 C, no single data type is correct for null pointers in all
contexts, particularly in actual parameters to functions.  These should
ALWAYS be written as NULL (or 0) cast to pointers of the correct type.
The best definition of NULL in <stdio.h> for these implementations is the
integer constant 0.  Some of us would even argue that that is the only
completely correct choice.

In X3J11 C, if a function prototype is in scope, casting of function
parameters is automatically done, and either (void *)0 or 0 is a
correct definition for NULL.

I recommend that you assume that NULL is defined to be the int constant
0 (even if it isn't on your current system), and always cast it to the
correct pointer type when used as an actual parameter.  This practice
will continue to work under X3J11.

dave@ur-valhalla.UUCP (Dave Carlson) (11/05/86)

A potential problem I smacked into yesterday when porting BSD to SV/AT
is ioctl(2) expects as the third argument:
union	{ int iarg;
	char *cparg;}
Problem is that the union will pull 4 bytes off the stack (in large model)
but the program calling with an integer will only push 2 bytes.  Oh S*$&!
I cast my integer args long and everything seems ok but what a pain...

I'm always a bit wary when I have to watch even system calls.
Raver dave

guy@sun.uucp (Guy Harris) (11/05/86)

> I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or,
> in the brave new world of ANSI X-whatever, "(void *) 0"?  This should
> do all the right things.

No, it shouldn't.  Passing a "(char *)0" to a routine that expects an "int
*" of some sort is NOT guaranteed to work.  If, in fact, you have a machine
on which "char *" is longer than "int *", it is very unlikely to work.

In the brave new world of ANSI X3J11, the right thing to do is to use
function prototypes; if you do this, almost all the 0's will be
automatically converted into null pointers of the appropriate type by the
compiler.  (It still won't work for "execl"; if you hack NULL to be
"(char *)0", it fixes *this* case, but it may not work for some routine that
expects an "(int *)0" at the end of its argument list.)
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

guy@sun.uucp (Guy Harris) (11/05/86)

> To get *all* the right things, we use:
> 
> 	#ifdef	lint
> 	#   define	null	0
> 	#else
> 	#   define	null	(char *)0
> 	#endif
> 
> since lint doesn't understand that comparing an (int *) variable with a
> (char *)0 is legitimate.

If you use that particular construct, you will get a lot of perfectly
legitimate "lint" complaints about argument mismatches when you pass a
"null" to a routine that expects a pointer of some sort.  Since, given the
rationale for this construct, you presumably want to keep "lint" as quiet as
possible, you presumably then cast "null" to the appropriate type.  Given
that, what does the non-"lint" arm of the conditional buy you, other than
fixing up a few calls to things like "execl", which are easy enough to fix
manually with casts?
-- 
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com (or guy@sun.arpa)

wmam@sphinx.UChicago.UUCP (tony mason) (11/06/86)

In article <188@vsedev.VSE.COM> ron@vsedev.VSE.COM (Ron Flax) writes:
>One other unrelated problem I have with Microport  Unix is  that for one
>reason or  another  the system  seems to  run for  a while  then when it
>decides its had enough it just  plain goes  south.   It appears  to be a
>deadlock situation  since  terminals  that  had  active  sessions  going
>continue to echo keystroke even  though it  doesn't respond  to them and
>non-active sessions (ie.  getty's running) do NOT echo keystrokes.  This
>obviously quite annoying as you might imagine...   One  other thing that
>is interesting is that I  know of  two other  sites with  the exact same
>problem on  different  hardware,  but  Microport claims  they have never
>heard of it?  Has anyone else  seen this  behavior?   Incidentally I was
>running SCO Xenix  V successfully  for about  6 months  prior to getting
>Microport Unix.  Microport are you listening 8-)
>

While running with SCO Xenix V all spring, we found that it would
periodically do EXACTLY what you are describing.  It made no difference what
machine we used (IBM AT, SPERRY IT, even ALTOS 2086)  it would die.  After
much in-depth research, and discussion with SCO's technical support
(overworked, harried people it often took a week just to get to talk to) it
turns out that it isn't too hard to get this problem to occur - just write a
large model program on the 80286 that uses sbrk() (and is returning large
pointers) and doesn't de-allocate at the end of the program (after all, why
do that?  The system takes care of it right?) this will lead to death.
Symptoms are:

	1. Terminals still echo characters
	2. Disk activity periodically (sync?)
	3. NOTHING can be done (except a reset) to get it back.

This is the infamous LARGE MODEL DEATH.  I was told by SCO that they had no
fix for it, and that their technical engineers were stumped (something like,
five of the last five "fixes" in house had failed to work.)

Naturally, we tested this out on other machines, and yes, it occurs on them
all.  (This was disasterous because the product was using INFORMIX - which
did have some large model pieces).

Perhaps this is what you are experiencing (if not, it is an AMAZING
coincidence).

wmam@sphinx.UChicago.UUCP (tony mason) (11/06/86)

In article <405@maynard.UUCP> campbell@maynard.UUCP (Larry Campbell) writes:
>In article <347@prairie.UUCP> dan@prairie.UUCP (Daniel M. Frank) writes:
>>In article <245@rabbit1.UUCP> barber@rabbit1.UUCP (Steve Barber) writes:
>>>Another common problem is passing NULL as pointer argument.  NULL is
>>>#defined as 0, which is 2 bytes.  Large model pointers are 4 bytes, so
>>>the stack frame is now basically garbage.
>>
>>   This isn't really true.  Code in stdio.h for the SV/286 release
>>checks your memory model, and if it is large, defines NULL to be 0L,
>>which is the same size as a pointer.  It doesn't please lint, so the
>>best solution is still to cast it as appropriate (like (char *)0),
>>but you ARE generally safe, as long as you include stdio.h.
>
>I wonder why stdio.h doesn't just declare NULL as "(char *) 0", or,
>in the brave new world of ANSI X-whatever, "(void *) 0"?  This should
>do all the right things.

Note that in SCO XENIX (a/k/a MICROSOFT XENIX) they have declared NULL to be
of type (char *)0.  Of course, you always have someone who will abuse this by
doing something stupid such as:

	char	buf[10];

	buf[0] = NULL;

but they will learn!

The best practice is to cast it correctly (it sure makes lint happy!).


Tony Mason				> No opinions expressed here. Only cold hard
University of Chicago   > facts.

    uucp:  ...ihnp4!gargoyle!sphinx!wmam, ...ihnp4!gargoyle!euler!tony
    bitnet:   wmam%sphinx@UChicago.Bitnet
    US. Lotto System (bet your 22 cents that it will get there!!!)
			 3854 S. Archer               (312) 254-2114 home
    	     Chicago, IL  60632           

david@ukma.uky.csnet (David Herron, NPR Lover) (11/07/86)

In article <840@ur-valhalla.UUCP> dave@valhalla.UUCP (Dave Carlson) writes:
>A potential problem I smacked into yesterday when porting BSD to SV/AT
>is ioctl(2) expects as the third argument:
>union   { int iarg;
>        char *cparg;}
>Problem is that the union will pull 4 bytes off the stack (in large model)
>but the program calling with an integer will only push 2 bytes.  Oh S*$&!
>I cast my integer args long and everything seems ok but what a pain...

Argh!  And you're doing a port of an operating system???

UNIONS are the SAME size regardless of WHICH part of them you use!

A user which passes an int to a routine expecting a union is ASKING
for trouble!

Argh!
-- 
David Herron,  cbosgd!ukma!david, david@UKMA.BITNET, david@ms.uky.csnet
(I'm also "postmaster", "news", "netnews", "uucp", "mmdf", and ...)
(And also the ACM chapter chairperson.)
(And even an all-around nice guy.  Aren't you lucky to get something from me?)

gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/08/86)

In article <5068@ukme.ukma.uky.csnet> david@ukme.UUCP (David Herron, NPR Lover) writes:
-In article <840@ur-valhalla.UUCP> dave@valhalla.UUCP (Dave Carlson) writes:
->A potential problem I smacked into yesterday when porting BSD to SV/AT
->is ioctl(2) expects as the third argument:
->union   { int iarg;
->        char *cparg;}
->Problem is that the union will pull 4 bytes off the stack (in large model)
->but the program calling with an integer will only push 2 bytes.  Oh S*$&!
->I cast my integer args long and everything seems ok but what a pain...
-
-Argh!  And you're doing a port of an operating system???
-
-UNIONS are the SAME size regardless of WHICH part of them you use!
-
-A user which passes an int to a routine expecting a union is ASKING
-for trouble!

Oh, good grief!  Mr. Carlson is talking about ioctl(), which is a
well-known function whose third argument has a type that depends on
its second argument's value; usually it's an (int) or a (struct termio *).
The problem is not his; rather it is due to the SV/AT implementor
changing ioctl()'s third argument to be a union.  This is in violation
of the SVID and of common sense, since (as Mr. Carlson reports) this
breaks correctly-written code.