Skip to content

Fix TFImporter diagnostic mode segfault#20402

Merged
opencv-pushbot merged 1 commit intoopencv:masterfrom
rogday:tf_diag_dummy
Jul 16, 2021
Merged

Fix TFImporter diagnostic mode segfault#20402
opencv-pushbot merged 1 commit intoopencv:masterfrom
rogday:tf_diag_dummy

Conversation

@rogday
Copy link
Copy Markdown
Member

@rogday rogday commented Jul 13, 2021

This PR adds DummyLayer and replaces all failed to initialize layers with it. This solves the issue of memory corruption in getLayerShapes() because DummyLayer just throws an exception in every function.

Test data is at opencv/opencv_extra#882

opencv_extra=tf_diag_dummy

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on a code under GPL or other license that is incompatible with OpenCV
  • The PR is proposed to proper branch
  • There is reference to original bug report and related work
  • There is accuracy test, performance test and test data in opencv_extra repository, if applicable
    Patch to opencv_extra has the same branch name.
  • The feature is well documented and sample code can be built with the project CMake

@rogday rogday force-pushed the tf_diag_dummy branch 2 times, most recently from 55aee70 to d7b19eb Compare July 13, 2021 12:11
@rogday rogday requested a review from dkurt July 13, 2021 12:55
*
* Intended for internal use only in conjunction with DNN_DIAGNOSTIC_RUN.
*/
void replaceLayer(const String &name, const String &type, LayerParams &params);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, we don't need this in public API (User visible). The same comment is about DummyLayer.
use dnn/src/dnn_common.hpp instead.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 &params);
};

class CV_EXPORTS DummyLayer : public Layer
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DummyLayer -> NotImplementedLayer?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Comment on lines +5 to +7
// Copyright (C) 2021, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this unrelated copyright. The first 3 lines from Wiki page is enough.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@rogday rogday force-pushed the tf_diag_dummy branch 2 times, most recently from 3ca3586 to c052152 Compare July 14, 2021 08:24
Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ptr<Layer>(new

makePtr should be used instead (similar to std::make_shared)

Comment on lines +2733 to +2736
if (DNN_DIAGNOSTICS_RUN)
{
LayerFactory::registerLayer("NotImplemented", notImplementedRegisterer);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it used?
should we restore log level in destructor?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +27 to +28
Ptr<Layer> notImplementedRegisterer(LayerParams &params);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need that in dnn_common.hpp anymore.

Implementation can be placed near NotImplemented::Register()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in TFimporter::parseNode.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is not NotImplemented::Register()? (or nothing because it is handled in enableModelDiagnostics())

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's imagine TFImporter doesn't know some layer. It will be registered in order to not flood the output with errors about it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If diagnostic mode is not enabled then strategy must be "fail fast". We should not eat problems.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am indeed talking about the behavior of this function with diagnostic mode turned on.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 name
  • unregisterLayerTypes() (called by enableModelDiagnostics(false)) - cleanup all previously registered layer's types saved on registration

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will push changes in a few hours. I added LayerHandler class which manages these layers and doesn't need to call registerLayer.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved.

static Ptr<Layer> create(const LayerParams &params);

static void Register();
static void unRegister();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a reserved keyword.

CV_DEPRECATED std::vector<Mat> finalize(const std::vector<Mat> &inputs)
{
CV_Error(Error::StsNotImplemented, msg);
return {};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CV_Error() doesn't return (it throws or abort()).
It is properly marked as [[noreturn]] for popular compilers.
All statements below should be removed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@rogday rogday removed the request for review from dkurt July 16, 2021 12:34
Copy link
Copy Markdown
Member

@alalek alalek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look good to me 👍

@opencv-pushbot opencv-pushbot merged commit b61a55e into opencv:master Jul 16, 2021
@rogday rogday deleted the tf_diag_dummy branch July 16, 2021 17:59
@alalek alalek mentioned this pull request Oct 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants