Fix TFImporter diagnostic mode segfault#20402
Conversation
55aee70 to
d7b19eb
Compare
| * | ||
| * Intended for internal use only in conjunction with DNN_DIAGNOSTIC_RUN. | ||
| */ | ||
| void replaceLayer(const String &name, const String &type, LayerParams ¶ms); |
There was a problem hiding this comment.
IMHO, we don't need this in public API (User visible). The same comment is about DummyLayer.
use dnn/src/dnn_common.hpp instead.
There was a problem hiding this comment.
Moved NotImplemented layer to dnn_common.hpp. replaceLayer became a part of addLayer under if (DNN_DIAGNOSTICS_RUN && type == "NotImplemented") which will otherwise throw an exception as before.
| static Ptr<Layer> create(const LayerParams ¶ms); | ||
| }; | ||
|
|
||
| class CV_EXPORTS DummyLayer : public Layer |
There was a problem hiding this comment.
DummyLayer -> NotImplementedLayer?
| // Copyright (C) 2021, Intel Corporation, all rights reserved. | ||
| // Third party copyrights are property of their respective owners. | ||
|
|
There was a problem hiding this comment.
Please remove this unrelated copyright. The first 3 lines from Wiki page is enough.
3ca3586 to
c052152
Compare
alalek
left a comment
There was a problem hiding this comment.
Is it possible to add some simple test case for that? (to ensure that this would not crash anymore)
|
|
||
| Ptr<Layer> NotImplemented::create(const LayerParams& params) | ||
| { | ||
| return Ptr<Layer>(new NotImplementedImpl(params)); |
There was a problem hiding this comment.
Ptr<Layer>(new
makePtr should be used instead (similar to std::make_shared)
| if (DNN_DIAGNOSTICS_RUN) | ||
| { | ||
| LayerFactory::registerLayer("NotImplemented", notImplementedRegisterer); | ||
| } |
There was a problem hiding this comment.
We have other importers too with similar problems.
What would happen with multiple registration attempts?
IMHO, register should go into NotImplemented as static method.
| Net net = readNetFromTensorflow(netPath, netConfig); | ||
| } | ||
| private: | ||
| cv::utils::logging::LogLevel logLevel; |
There was a problem hiding this comment.
is it used?
should we restore log level in destructor?
There was a problem hiding this comment.
I deleted it already. Originally, yes, in constructor I was silencing logs and in the destructor the appropriate level was restored, but in event of test failure we would loose logs. Report.xml shouldn't contain stderr output and I decided to leave logs be.
modules/dnn/src/dnn_common.hpp
Outdated
| Ptr<Layer> notImplementedRegisterer(LayerParams ¶ms); | ||
|
|
There was a problem hiding this comment.
we don't need that in dnn_common.hpp anymore.
Implementation can be placed near NotImplemented::Register()
There was a problem hiding this comment.
It is used in TFimporter::parseNode.
There was a problem hiding this comment.
Why is not NotImplemented::Register()? (or nothing because it is handled in enableModelDiagnostics())
There was a problem hiding this comment.
Let's imagine TFImporter doesn't know some layer. It will be registered in order to not flood the output with errors about it.
There was a problem hiding this comment.
If diagnostic mode is not enabled then strategy must be "fail fast". We should not eat problems.
There was a problem hiding this comment.
I am indeed talking about the behavior of this function with diagnostic mode turned on.
There was a problem hiding this comment.
Got it. It is registered under a new name.
There is another problem:
- "NotImplemented" is unregistered when we call
enableModelDiagnostics(false); - these unknown layers don't.
Perhaps we should disallow turning off diagnostic mode if it is already enabled. This would be OK for tool, but this would cause problems with tests.
BTW, NotImplemented::Register() can accept the "name" string parameter.
There was a problem hiding this comment.
The last problem can be resolved through singleton for registered NotImplemented layers. It should provide two methods:
registerLayerType(const std::string& name)- register and save used nameunregisterLayerTypes()(called byenableModelDiagnostics(false)) - cleanup all previously registered layer's types saved on registration
There was a problem hiding this comment.
I will push changes in a few hours. I added LayerHandler class which manages these layers and doesn't need to call registerLayer.
| static Ptr<Layer> create(const LayerParams ¶ms); | ||
|
|
||
| static void Register(); | ||
| static void unRegister(); |
There was a problem hiding this comment.
Register -> register
https://github.com/opencv/opencv/wiki/Coding_Style_Guide#naming-conventions
There was a problem hiding this comment.
This is a reserved keyword.
| CV_DEPRECATED std::vector<Mat> finalize(const std::vector<Mat> &inputs) | ||
| { | ||
| CV_Error(Error::StsNotImplemented, msg); | ||
| return {}; |
There was a problem hiding this comment.
CV_Error() doesn't return (it throws or abort()).
It is properly marked as [[noreturn]] for popular compilers.
All statements below should be removed.
This PR adds
DummyLayerand replaces all failed to initialize layers with it. This solves the issue of memory corruption ingetLayerShapes()becauseDummyLayerjust throws an exception in every function.Test data is at opencv/opencv_extra#882
opencv_extra=tf_diag_dummyPull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
Patch to opencv_extra has the same branch name.