Waveform with one element is not set

Bug #1389298 reported by Ralph Lange
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
EPICS Base
Fix Released
Critical
Unassigned

Bug Description

Reported by Vishnukumar Patel <email address hidden>

In 3.15, arrays with one element are not written to correctly.

The attached database contains a random generating calc record ("rndm"), and two waveform records of type DOUBLE, with one and two elements ("wave1", "wave2").

Using 'camonitor wave1 wave2', running the IOC on 3.14 (regular softIoc binary) looks good:

$ camonitor -#2 wave1 wave2
wave1 2014-11-04 17:11:39.943950 1 5.53216
wave2 2014-11-04 17:11:39.943956 2 5.53216 0
wave1 2014-11-04 17:11:40.043655 1 2.59342
wave2 2014-11-04 17:11:40.043666 2 2.59342 0

The same command against a 3.15.0.2 IOC yields:

$ camonitor -#2 wave1 wave2
wave1 2014-11-04 17:11:22.568008 1 0
wave2 2014-11-04 17:11:22.568014 2 4.99763 0
wave1 2014-11-04 17:11:22.668243 1 0
wave2 2014-11-04 17:11:22.668306 2 3.18135 0

Obviously, the 1 element array does not get updated properly.

The example is using .CP input links. Changing the mechanism to FLNK plus .NPP input does not change the faulty behavior.

Tags: db
Revision history for this message
Ralph Lange (ralph-lange) wrote :
Andrew Johnson (anj)
Changed in epics-base:
status: New → Confirmed
importance: Undecided → Critical
Revision history for this message
Andrew Johnson (anj) wrote :

Both caput and dbpf directly to the waveform do work, it's going through a link that seems to be the problem. I will try to look more closely tomorrow unless someone else gets there first.

Revision history for this message
Ralph Lange (ralph-lange) wrote :

Running softIoc in the debugger I have the impression that the prec->bptr array is being updated correctly.
Both bptr arrays (of wave1 and wave2) get the "random" bit pattern written into the first element.
Strange.

Revision history for this message
Andrew Johnson (anj) wrote :

Hi Ralph,

Agreed, the value is being correctly copied into the bptr array by the input link. The issue is downstream, in dbAccess and the dbEvent stuff, and relates to the changes made in Michael's array-opt branch to allow double-buffering. There are actually several bugs, the simplest one is in dbGet(), one in dbPut(), and a more complex one related to dbEvent and the db_field_log handling which I don't fully understand.

Michael's change [probably prompted by me; I don't want to blame him for this] moved the statement
    paddr->pfield = prec->bptr;
from wf::cvt_dbaddr() to wf::get_array_info(), and modified the db_post_events() call in wf::monitor() to use the address of the VAL field instead of prec->bptr as the monitor address.

Unfortunately in dbGet(), the "check for array" code only calls prset->get_array_info() if no_elements > 1, so for a wf record with NELM=1 the pfield address used by dbGet() is now that of the void *val member, not the contents of prec->bptr. This can be fixed by removing (no_elements > 1) from the condition needed to call the get_array_info() routine.

There is a similar problem in dbPut() which needed a little bit more work; it must be able to call prset->get_array_info() even for single-element arrays in order to let the record type set paddr->pfield, and similarly call prset->put_array_info() afterwards.

Unfortunately the above fixes do not affect monitors. When subscribing to a single-element dbChannel object, db_add_event() sets the pevent->useValque flag in the subscription. This causes the db_field_log object created by db_create_event_log() to have type = dbfl_type_val (for larger arrays it has type = dbfl_type_rec). Unfortunately this setting also prevents the dbGet() routine from calling prset->get_array_info(), so the value copied into the event queue again comes from the VAL field again, not from BPTR.

Just removing the (pfl->type == dbfl_type_rec) condition from dbGet() is not correct; hopefully you'll have a better idea of how to do that part.

I have to switch tasks for a couple of days now, so this problem is now yours to take further if you can. I've attached my fixes so far as a patch file. I will also attach another patch containing my debug printf() statements — turn off scanning of your waveforms if you apply this though, it's verbose!

- Andrew

Revision history for this message
Andrew Johnson (anj) wrote :

Verbose printf() statements for debugging purposes only!

Revision history for this message
Andrew Johnson (anj) wrote :

This patch resolves the problem by not setting pevent->useValque if the field is marked as SPC_DBADDR. This is less efficient than it could be, but is a much simpler solution than the alternative.

The change I made to dbChannel.c looks like it was a typo in the original, please confirm.

- Andrew

Revision history for this message
Ralph Lange (ralph-lange) wrote :

Yes, this patch works.

Confirmed with the simple test db that is part of this bug report.
Confirmed with the extended std/rec/test/arrayOpTest that I added in Rev12593.

The dbChannel.c issue is indeed a typo. Probably that expression was not inverted correctly at some time.
The array copy must be made exactly once, when the first filter of a possible chain is being called, and the field_log points to the record. When the field_log type is not type_rec, nothing has to be done.

Thanks a lot!!

Andrew Johnson (anj)
Changed in epics-base:
status: Confirmed → Fix Committed
Andrew Johnson (anj)
Changed in epics-base:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.