Fix #11026 - Bad thermostat control type value results in crash due to null schedule pointer#11074
Merged
Myoldmopar merged 7 commits intodevelopfrom May 28, 2025
Merged
Conversation
jmarrec
commented
May 20, 2025
Comment on lines
+1106
to
+1116
| "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 |
Contributor
Author
There was a problem hiding this comment.
Test reproduces the defect
Comment on lines
+1149
to
+1171
| 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); |
Contributor
Author
There was a problem hiding this comment.
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
jmarrec
commented
May 20, 2025
Comment on lines
703
to
+732
| 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; | ||
| } |
Contributor
Author
There was a problem hiding this comment.
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
|
Contributor
Author
Myoldmopar
approved these changes
May 28, 2025
Member
Myoldmopar
left a comment
There was a problem hiding this comment.
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; | ||
| } |
Member
There was a problem hiding this comment.
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.
Member
|
Looking good here, merging this. Thanks @jmarrec |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

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