Mailing List Archive



Back to the month index Back to the list index

Kim Rudeen (rudeen@caesun16.msd.ray.com)
Tue, 3 Sep 96 15:06:03 EDT


From: Kim Rudeen <rudeen@caesun16.msd.ray.com>
Message-Id: <199609031906.PAA02233@caehp6.msd.ray.com>
Subject: Re: [mSQL] Selecting REAL field problems : HP-UX and SGI IRIX
Date: Tue, 3 Sep 96 15:06:03 EDT

>
> First of all, on August 27th, Kim Rudeen <rudeen@caesun16.msd.ray.com> wrote :
>
> >I am using MSQL on HP-UX-A.09.05-9000_715.
> >
> >Is this by any chance a problem with accessing REAL values?
>
> That was the original message that rang a bell here. We had
> a problem selecting real values from databases using mSQL daemons compiled
> using the HP-UX C compiler; trying to select a real causes the daemon to
> crash. The problem's affected both mSQL versions 1.0.14 and 1.0.16.
>
>
> Kim, is that the problem you had ? Here I originally worked round it by

I'm resending this message since my first attempt seemed to get lost.

Yes, that is exactly the problem I had. I had thought it had been
fixed in some way, since it didn't occur for msql-1.0.16 for my
test case. If the problem is still there, I need to recompile.

Here is a copy of my original report, including a test case, a diagnosis,
other places in the mSQL code where the same problem is likely to occur,
a simple test case, a workaround (similar to yours) and suggested code
fixes:

/--------------------------------------------------------/

This is to report a OS or platform specific problem with
mSQL, and some suggested fixes. I would be interested in
any extensions or improvements.

This problem occurs after compiling mSQL using the standard
HP-UX 9.0.5 compiler /bin/cc. Other platforms or compilers
may not have it, for reasons that will become clear.

The problem occurs when trying to access a REAL value. The
message

        ERROR : MSQL server has gone away

appears, and the msqld server has to be restarted.

The following script creates the problem:

#
# commands causing error
#

CREATE TABLE problem (
      name CHAR(10),
      num INT,
      discount REAL
    )\g
    

INSERT INTO problem VALUES ('item 9999',999,1.0)\g

SELECT discount FROM problem\g

#
# end of error script
#

The error occurs when the SELECT command is entered.

The problem is in function extractValues() in msqldb.c. Function
extractValues() contains the following code:

        double *fp;
        char buf[8];
           .
           .
           .
                case REAL_TYPE:
                        bcopy8(row + *offset + 1,buf);
                        fp = (double *)buf;
                        curField->value =(val_t *)
                                fillValue(fp,REAL_TYPE);

In this code, the 8 bytes indexed by row and offset, which contain
the REAL value to be read, are packed into character array buf[8].
The variable fp, a pointer to double, is set to point to buf and
passed to function fillValue() in msql_proc.c.

Function fillValue() contains:

val_t *fillValue(val,type,length)
        char *val;
        int type,
                length;
           .
           .
           .
                case REAL_TYPE:
                        new->val.realVal = (double) * (double *)val;
                        break;

This code is used to extract the real number in val, a character
pointer, and load it into new->val.realVal.

A bus error occurs when variable val is dereferenced using
(double) *, just after being cast as a pointer to double.

The problem is due to the alignment of double variables expected by
the HP-UX 9.0.5 /bin/cc compiler. Double variables are expected by
default to be aligned; that is, to have a memory address that is
a multiple of 8. If a double variable pointer accesses an address
that is NOT a multiple of 8, we get a bus error. Variable val is
pointing to the address of buf[8], which is not aligned as expected.
Bang.

I have two fixes. One is to create a union containing buf[8] and
a double:

union
    {
    double dbuf;
    char buf[8];
    } ubuf;

This forces the 8 bytes of memory to be aligned as a double variable.
Only the character portion of ubuf is used:

    bcopy8(row + *offset + 1,ubuf.buf);
    fp = (double *) ubuf.buf;

I have tried this, and it corrects the problem. The difficulty is
that there are at least two other functions in msqldb.c alone
where this same error is likely to occur, findKeyValue() and
compareRows(). It may occur in other mSQL functions as well, and
I don't have the time or funding to locate and correct them.

The second fix is an HP-UX 9.0.5 compiler option that "allows
pointers to access non-natively aligned data." This option apparently
tells the compiler not to assume that double variables are aligned at
multiples of 8 bytes. The compiler option I am using is +u1, which
assumes single byte alignment.

I am applying this option by modifying the CFLAGS entry in site.mm.in:
  
  CFLAGS= -g +u1 -I$(TOP)/ $(EXTRA_CFLAGS)

By the way, is there another safe way to do this? This modification
generates a list of makedepends warnings. Also, could this have any
unwanted side effects? Should it be limited to compiling

The problem with this approach is that "use of this option may reduce
the efficiency of generated code." That isn't a problem for me right
now, but it certainly could be for large data bases.

Here is a simple test case that duplicates the problem (for me at least):

/* error.c - Error example program */

#include <stdio.h>

void fill();

void main()
{
int i1,i2,i3;
char buf[8];
double *fp;

    fp = (double *) buf;
    fill(fp);
}

void fill(val)
char * val;
{
double *pd;
double d1;
 
       pd = (double *) val;
       d1 = *pd;
}

The bus error occurs at the line

       d1 = *pd;

The error does not occur if the following compilation
is used:

       cc -o error -g +u1 error.c

Here is the same program modified to fix the problem using
a union:

/* error_fix.c - Error fix example program */

#include <stdio.h>

void fill();

void main()
{
int i1,i2,i3;
union
    {
    double dbuf;
    char buf[8];
    } ubuf;
double *fp;

    fp = (double *) ubuf.buf;
    fill(fp);
}

void fill(val)
char * val;
{
double *pd;
double d1;
 
       pd = (double *) val;
       d1 = *pd;
}

It seems to me that this is a portability problem, and that the
best way to fix it is to modify the source code to avoid the
situation.

Kim Rudeen
--------------------------------------------------------------------------
To remove yourself from the Mini SQL mailing list send a message containing
"unsubscribe" to "unsubscribe" to msql-list-request@bunyip.com. Send a message containing
"info msql-list" to majordomo@bunyip.com for info on monthly archives of
the list. For more help, mail owner-msql-list@bunyip.com NOT the msql-list!