Skip to content

Commit

Permalink
[darwin-framework-tool] Automatically check for leaks on shutdown if …
Browse files Browse the repository at this point in the history
…enable_leak_checking is true
  • Loading branch information
vivien-apple committed Oct 8, 2024
1 parent 1dadbe4 commit b1f1fad
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
8 changes: 8 additions & 0 deletions examples/darwin-framework-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ declare_args() {

# Disable generating compiler database by default
generate_compilation_database = false

# Enable automatic leak checks before the application exits
enable_leak_checking = false
}

sdk = "macosx"
Expand Down Expand Up @@ -219,6 +222,7 @@ executable("darwin-framework-tool") {
"commands/provider/OTASoftwareUpdateInteractive.mm",
"commands/storage/Commands.h",
"commands/storage/StorageManagementCommand.mm",
"debug/LeakChecker.mm",
"logging/logging.mm",
"main.mm",
]
Expand Down Expand Up @@ -280,6 +284,10 @@ executable("darwin-framework-tool") {
defines += [ "MTR_ENABLE_PROVISIONAL=1" ]
}

if (enable_leak_checking) {
defines += [ "DFT_ENABLE_LEAK_CHECKING=1" ]
}

public_configs = [ ":config" ]

output_dir = root_out_dir
Expand Down
28 changes: 28 additions & 0 deletions examples/darwin-framework-tool/debug/LeakChecker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#pragma once

/*
* This function performs a memory leak check if the build flag `enable_leak_checking` is set to true
* If leaks are detected, it overrides the provided exit code with `EXIT_FAILURE`.
*
* @param exitCode The initial exit code to return if no leaks are detected or if leak checking is disabled.
* @return `EXIT_FAILURE` if leaks are detected and leak checking is enabled; otherwise, the original `exitCode`.
*/
int ConditionalLeaksCheck(int exitCode);
70 changes: 70 additions & 0 deletions examples/darwin-framework-tool/debug/LeakChecker.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

#include "LeakChecker.h"

#import <Foundation/Foundation.h>
#include <unistd.h> // For getpid()

@interface LeakChecker : NSObject
- (BOOL)hasMemoryLeaks;
@end

@implementation LeakChecker

- (BOOL)hasMemoryLeaks
{
pid_t pid = getpid();
auto * pidString = [NSString stringWithFormat:@"%d", pid];

auto * task = [[NSTask alloc] init];
task.launchPath = @"/usr/bin/leaks";
task.arguments = @[ pidString ];

auto * pipe = [NSPipe pipe];
task.standardOutput = pipe;
task.standardError = pipe;

NSFileHandle * fileHandle = [pipe fileHandleForReading];
[task launch];
[task waitUntilExit];

int exitCode = [task terminationStatus];
if (exitCode) {
NSData * data = [fileHandle readDataToEndOfFile];
NSString * output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", output);
return YES;
}

return NO;
}

@end

int ConditionalLeaksCheck(int exitCode)
{
#ifdef DFT_ENABLE_LEAK_CHECKING
auto * leakChecker = [[LeakChecker alloc] init];
if ([leakChecker hasMemoryLeaks]) {
return EXIT_FAILURE;
}
#endif // DFT_ENABLE_LEAK_CHECKING

return exitCode;
}
6 changes: 5 additions & 1 deletion examples/darwin-framework-tool/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#import <Matter/Matter.h>

#import "debug/LeakChecker.h"
#import "logging/logging.h"

#include "commands/bdx/Commands.h"
Expand All @@ -35,11 +36,13 @@

int main(int argc, const char * argv[])
{
int exitCode = EXIT_SUCCESS;
@autoreleasepool {
dft::logging::Setup();

Commands commands;
registerCommandsBdx(commands);
registerCommandsLeaks(commands);
registerCommandsPairing(commands);
registerCommandsDelay(commands);
registerCommandsDiscover(commands);
Expand All @@ -49,6 +52,7 @@ int main(int argc, const char * argv[])
registerCommandsStorage(commands);
registerCommandsConfiguration(commands);
registerClusters(commands);
return commands.Run(argc, (char **) argv);
exitCode = commands.Run(argc, (char **) argv);
}
return ConditionalLeaksCheck(exitCode);
}

0 comments on commit b1f1fad

Please sign in to comment.