EPICS Home

Experimental Physics and Industrial Control System


 
1994  1995  <19961997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  <19961997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: DBR_STRING get for DBF_DOUBLE (Possible Problem)
From: Marty Kraimer <[email protected]>
To: [email protected]
Date: Fri, 07 Jun 1996 09:41:47 -0500
A possible problem exists when a DBR_STRING request is made
for a DBF_DOUBLE field. The problem exists in release 3.12.2
and possibly earlier releases. In order for the problem to appear
the following must be true:
 
1) Locally written record support is used.
2) The get_precision routine calls recGblGetPrec
   without setting precision to some default.
   NOTE: ALL record support supplied with EPICS base are OK.
 
 
The problem was discovered by Tim Mooney (APS/XFD).
In his case the result was a hard crash of his IOC,
which made it really fun to find the problem.
 
The gory details are as follows:
 
Unless get_precision sets precision to some default
no other ioc code does. Things start with
an internal conversion routine called getDoubleString.
The final routine involved is routine cvtDoubleToString.
It begins with the code:
 
int cvtDoubleToString(
        double flt_value,
        char  *pstr_value,
        unsigned short precision)
{
        unsigned short  got_one,i;
        long            whole,iplace,number,fraction,fplace;
        double          ftemp;
        char            *startAddr;
 
        /* can this routine handle this conversion */
        if (precision > 8 || flt_value > 10000000.0 || flt_value < -10000000.0)
{
                if (precision > 8 || flt_value > 1e16 || flt_value < -1e16) {
                    /*if(precision>17) precision=17;*/
                    sprintf(pstr_value,"%*.*e\0",precision+7,precision,
                        flt_value);
        ...
 
NOTE:   The commented out line
        /*if(precision>17) precision=17;*/
        Is NOT present in the 3.12.2 version.
 
Since precision was never initialized it can have any value
between 0 and 65535. In Tim Mooneys case it had the
value 0xeee (vxWorks initializes stack to this value).
Thus the sprintf generates a string of length 0xeee + 7.
Since the receive buffer is 40 bytes (it was a Channel
Access call) it wipes out some portion of memory.
 
Solution:
 
For 3.12.2 make sure that any locally written record support
codes the get_precision starting as follows:
 
static long get_precision(DBADDR *paddr, long *precision)
{
    aiRecord    *pai=(aiRecord *)paddr->precord;
 
    *precision = pai->prec;
 
For 3.13 the following will be done.
 
1) getDoubleString (and corresponding fast convert routine)
   initializes precision to 0.
2) cvtDoubleToString adds the commented out statement shown
   above.
 
All record support should still follow the example shown above.
 
 
Marty Kraimer


Navigate by Date:
Prev: PC-port status Bob Dalesio
Next: Drivers Fred Carter
Index: 1994  1995  <19961997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: PC-port status Bob Dalesio
Next: Drivers Fred Carter
Index: 1994  1995  <19961997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024