-
Notifications
You must be signed in to change notification settings - Fork 460
Fix #11026 - Bad thermostat control type value results in crash due to null schedule pointer #11074
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| "ZoneControl:Thermostat,", | ||
| " Zone1 Thermostat, !- Name", | ||
| " Zone1, !- Zone or ZoneList Name", | ||
| " Single HEATING Control Type Sched, !- Control Type Schedule Name", | ||
| " ThermostatSetpoint:SingleCooling, !- Control 1 Object Type", | ||
| " Thermostat Setpoint Single Cooling; !- Control 1 Name", | ||
|
|
||
| "Schedule:Constant,", | ||
| " Single HEATING Control Type Sched, !- Name", | ||
| " Control Type, !- Schedule Type Limits Name", | ||
| " 1; !- Hourly Value", // <-------- 1 = Single Heating, which is WRONG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test reproduces the defect
| GetZoneData(*state, ErrorsFound); | ||
| ASSERT_FALSE(ErrorsFound); | ||
|
|
||
| EXPECT_THROW(GetZoneAirSetPoints(*state), EnergyPlus::FatalError); | ||
| std::string const error_string = delimited_string({ | ||
| " ** Severe ** Control Type Schedule=SINGLE HEATING CONTROL TYPE SCHED", | ||
| " ** ~~~ ** ..specifies 1 (ThermostatSetpoint:SingleHeating) as the control type. Not valid for this zone.", | ||
| " ** ~~~ ** ..reference ZoneControl:Thermostat=ZONE1 THERMOSTAT", | ||
| " ** ~~~ ** ..reference ZONE=ZONE1", | ||
| " ** Severe ** GetStagedDualSetpoint: Errors with invalid names in ZoneControl:Thermostat:StagedDualSetpoint objects.", | ||
| " ** ~~~ ** ...These will not be read in. Other errors may occur.", | ||
| " ** Fatal ** Errors getting Zone Control input data. Preceding condition(s) cause termination.", | ||
| " ...Summary of Errors that led to program termination:", | ||
| " ..... Reference severe error count=2", | ||
| " ..... Last severe error=GetStagedDualSetpoint: Errors with invalid names in ZoneControl:Thermostat:StagedDualSetpoint objects.", | ||
| }); | ||
| EXPECT_TRUE(compare_err_stream(error_string, true)); | ||
| // Avoid calling InitZoneAirSetPoints(*state); but still initialize needed arrays | ||
| state->dataHeatBalFanSys->TempControlType.allocate(1); | ||
| state->dataHeatBalFanSys->TempControlTypeRpt.allocate(1); | ||
| state->dataHeatBalFanSys->zoneTstatSetpts.allocate(1); | ||
|
|
||
| CalcZoneAirTempSetPoints(*state); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc:1152: Failure
Expected: GetZoneAirSetPoints(*state) throws an exception of type EnergyPlus::FatalError.
Actual: it throws nothing.
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/Fixtures/EnergyPlusFixture.cc:211: Failure
Expected equality of these values:
expected_string
Which is: "\n"
stream_str
Which is: ""
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc:1154: Failure
Value of: compare_err_stream(error_string, true)
Actual: false
Expected: true
Process 92525 stopped
* thread #1, name = 'energyplus_test', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0x4c)
frame #0: 0x0000555556fc818a energyplus_tests`EnergyPlus::Sched::Schedule::getCurrentVal(this=0x0000000000000000) const at ScheduleManager.hh:275:20
272
273 Real64 getCurrentVal() const
274 {
-> 275 return EMSActuatedOn ? EMSVal : currentVal;
276 }
277
278 // Looks up a given Schedule value for an hour & timestep, minding whether DST is enabled or not| for (HVAC::SetptType setptType : HVAC::setptTypes) { | ||
| auto const &setpt = tempZone.setpts[(int)setptType]; | ||
| if (!setpt.isUsed) continue; | ||
|
|
||
| if (!setpt.isUsed) { | ||
| // Catch early issues | ||
| if (tempZone.setptTypeSched->hasVal(state, (int)setptType)) { | ||
| ShowSevereError(state, format("Control Type Schedule={}", tempZone.setptTypeSched->Name)); | ||
| ShowContinueError( | ||
| state, | ||
| format("..specifies {} ({}) as the control type. Not valid for this zone.", (int)setptType, setptTypeNames[(int)setptType])); | ||
| ShowContinueError(state, format("..reference {}={}", cZControlTypes((int)ZoneControlTypes::TStat), tempZone.Name)); | ||
| ShowContinueError(state, format("..reference ZONE={}", tempZone.ZoneName)); | ||
| ErrorsFound = true; | ||
| } | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix:
- if !setpt.isUsed but setptTypeSched hasVal => throw
c900f8a to
e1f17a1
Compare
```shell
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc:1152: Failure
Expected: GetZoneAirSetPoints(*state) throws an exception of type EnergyPlus::FatalError.
Actual: it throws nothing.
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/Fixtures/EnergyPlusFixture.cc:211: Failure
Expected equality of these values:
expected_string
Which is: "\n"
stream_str
Which is: ""
/home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/ZoneTempPredictorCorrector.unit.cc:1154: Failure
Value of: compare_err_stream(error_string, true)
Actual: false
Expected: true
Process 92525 stopped
* thread #1, name = 'energyplus_test', stop reason = signal SIGSEGV: address not mapped to object (fault address: 0x4c)
frame #0: 0x0000555556fc818a energyplus_tests`EnergyPlus::Sched::Schedule::getCurrentVal(this=0x0000000000000000) const at ScheduleManager.hh:275:20
272
273 Real64 getCurrentVal() const
274 {
-> 275 return EMSActuatedOn ? EMSVal : currentVal;
276 }
277
278 // Looks up a given Schedule value for an hour & timestep, minding whether DST is enabled or not
```
setptTypes was sized to 5 element, but only 4 were explicitly declared in the initializer. The 5th is zero initialized, which added SetptType::Uncontrolled cf https://godbolt.org/z/jbbzc9hnn
87f404a to
c37009f
Compare
|
Myoldmopar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great. Catching the control type value looks fine and the unit tests look sufficient.
| ShowContinueError(state, format("..reference {}={}", cZControlTypes((int)ZoneControlTypes::TStat), tempZone.Name)); | ||
| ShowContinueError(state, format("..reference ZONE={}", tempZone.ZoneName)); | ||
| ErrorsFound = true; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying to think about what happens if someone uses an API actuator to adjust the schedule value later. I know there are probably lots of places in the code that this could cause some issues, so not necessarily saying we need to do anything here, just thinking about possible impacts.
|
Looking good here, merging this. Thanks @jmarrec |

Pull request overview
Description of the purpose of this PR
This PR reverts to the 24.2.0 functionality which catches these errors during the GetInput (GetZoneAirSetPoints).
The Defect file, when run with this PR will no longer segfault, but will Fatal out as expected, as was done in 24.2.0
Pull Request Author
Reviewer