mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-08 12:37:49 +00:00
(fix): A memory leak was detected and fixed #46
The issue lay with the `ExtractSpecInfo()` method from within the `datamodel` module. There is a round of parsing that happens in another thread inside there, and a notification is pumped down a channel once done. The pronlem is that nothing was listening on that channel, so everything in those threads just kept piling up with the garbage collector unable to free any of it.
This commit is contained in:
@@ -81,12 +81,9 @@ func ExtractSpecInfo(spec []byte) (*SpecInfo, error) {
|
|||||||
_, openAPI2 := utils.FindKeyNode(utils.OpenApi2, parsedSpec.Content)
|
_, openAPI2 := utils.FindKeyNode(utils.OpenApi2, parsedSpec.Content)
|
||||||
_, asyncAPI := utils.FindKeyNode(utils.AsyncApi, parsedSpec.Content)
|
_, asyncAPI := utils.FindKeyNode(utils.AsyncApi, parsedSpec.Content)
|
||||||
|
|
||||||
parseJSON := func(bytes []byte, spec *SpecInfo) {
|
parseJSON := func(bytes []byte, spec *SpecInfo, parsedNode *yaml.Node) {
|
||||||
var jsonSpec map[string]interface{}
|
var jsonSpec map[string]interface{}
|
||||||
|
|
||||||
// no point in worrying about errors here, extract JSON friendly format.
|
|
||||||
// run in a separate thread, don't block.
|
|
||||||
|
|
||||||
if spec.SpecType == utils.OpenApi3 {
|
if spec.SpecType == utils.OpenApi3 {
|
||||||
switch spec.Version {
|
switch spec.Version {
|
||||||
case "3.1.0", "3.1":
|
case "3.1.0", "3.1":
|
||||||
@@ -100,9 +97,8 @@ func ExtractSpecInfo(spec []byte) (*SpecInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if utils.IsYAML(string(bytes)) {
|
if utils.IsYAML(string(bytes)) {
|
||||||
_ = yaml.Unmarshal(bytes, &jsonSpec)
|
_ = parsedNode.Decode(&jsonSpec)
|
||||||
jsonData, _ := json.Marshal(jsonSpec)
|
spec.SpecJSONBytes = &bytes
|
||||||
spec.SpecJSONBytes = &jsonData
|
|
||||||
spec.SpecJSON = &jsonSpec
|
spec.SpecJSON = &jsonSpec
|
||||||
} else {
|
} else {
|
||||||
_ = json.Unmarshal(bytes, &jsonSpec)
|
_ = json.Unmarshal(bytes, &jsonSpec)
|
||||||
@@ -112,6 +108,7 @@ func ExtractSpecInfo(spec []byte) (*SpecInfo, error) {
|
|||||||
spec.JsonParsingChannel <- true
|
spec.JsonParsingChannel <- true
|
||||||
close(spec.JsonParsingChannel)
|
close(spec.JsonParsingChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for specific keys
|
// check for specific keys
|
||||||
if openAPI3 != nil {
|
if openAPI3 != nil {
|
||||||
specVersion.SpecType = utils.OpenApi3
|
specVersion.SpecType = utils.OpenApi3
|
||||||
@@ -121,7 +118,7 @@ func ExtractSpecInfo(spec []byte) (*SpecInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse JSON
|
// parse JSON
|
||||||
go parseJSON(spec, specVersion)
|
parseJSON(spec, specVersion, &parsedSpec)
|
||||||
|
|
||||||
// double check for the right version, people mix this up.
|
// double check for the right version, people mix this up.
|
||||||
if majorVersion < 3 {
|
if majorVersion < 3 {
|
||||||
@@ -131,6 +128,9 @@ func ExtractSpecInfo(spec []byte) (*SpecInfo, error) {
|
|||||||
specVersion.Version = version
|
specVersion.Version = version
|
||||||
specVersion.SpecFormat = OAS3
|
specVersion.SpecFormat = OAS3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//return specVersion, nil
|
||||||
|
|
||||||
if openAPI2 != nil {
|
if openAPI2 != nil {
|
||||||
specVersion.SpecType = utils.OpenApi2
|
specVersion.SpecType = utils.OpenApi2
|
||||||
version, majorVersion, versionError := parseVersionTypeData(openAPI2.Value)
|
version, majorVersion, versionError := parseVersionTypeData(openAPI2.Value)
|
||||||
@@ -139,7 +139,7 @@ func ExtractSpecInfo(spec []byte) (*SpecInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse JSON
|
// parse JSON
|
||||||
go parseJSON(spec, specVersion)
|
parseJSON(spec, specVersion, &parsedSpec)
|
||||||
|
|
||||||
// I am not certain this edge-case is very frequent, but let's make sure we handle it anyway.
|
// I am not certain this edge-case is very frequent, but let's make sure we handle it anyway.
|
||||||
if majorVersion > 2 {
|
if majorVersion > 2 {
|
||||||
@@ -157,7 +157,7 @@ func ExtractSpecInfo(spec []byte) (*SpecInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse JSON
|
// parse JSON
|
||||||
go parseJSON(spec, specVersion)
|
parseJSON(spec, specVersion, &parsedSpec)
|
||||||
|
|
||||||
// so far there is only 2 as a major release of AsyncAPI
|
// so far there is only 2 as a major release of AsyncAPI
|
||||||
if majorVersion > 2 {
|
if majorVersion > 2 {
|
||||||
@@ -171,7 +171,7 @@ func ExtractSpecInfo(spec []byte) (*SpecInfo, error) {
|
|||||||
|
|
||||||
if specVersion.SpecType == "" {
|
if specVersion.SpecType == "" {
|
||||||
// parse JSON
|
// parse JSON
|
||||||
go parseJSON(spec, specVersion)
|
parseJSON(spec, specVersion, &parsedSpec)
|
||||||
|
|
||||||
specVersion.Error = errors.New("spec type not supported by vacuum, sorry")
|
specVersion.Error = errors.New("spec type not supported by vacuum, sorry")
|
||||||
return specVersion, specVersion.Error
|
return specVersion, specVersion.Error
|
||||||
|
|||||||
10
document.go
10
document.go
@@ -84,6 +84,16 @@ func NewDocument(specByteArray []byte) (Document, error) {
|
|||||||
d := new(document)
|
d := new(document)
|
||||||
d.version = info.Version
|
d.version = info.Version
|
||||||
d.info = info
|
d.info = info
|
||||||
|
|
||||||
|
// wait for json to be ready
|
||||||
|
// this needs to be deprecated at some-point
|
||||||
|
done := false
|
||||||
|
for !done {
|
||||||
|
select {
|
||||||
|
case <-info.JsonParsingChannel:
|
||||||
|
done = true
|
||||||
|
}
|
||||||
|
}
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user