Add android::base::GetPids() function to return all pids

We loop over /proc to iterate through pids in a lot of code, so let's
consolidate this into a single function in libbase.

Test: new unit test
Change-Id: I908fab90b603546d0e3e8b8acdc8dadfc3552d62
This commit is contained in:
Tom Cherry 2019-06-28 11:09:33 -07:00
parent 52f617176e
commit 13b1f34279
4 changed files with 136 additions and 0 deletions

View file

@ -53,6 +53,7 @@ cc_defaults {
"logging.cpp",
"mapped_file.cpp",
"parsenetaddress.cpp",
"process.cpp",
"properties.cpp",
"quick_exit.cpp",
"stringprintf.cpp",
@ -145,6 +146,7 @@ cc_test {
"parsedouble_test.cpp",
"parseint_test.cpp",
"parsenetaddress_test.cpp",
"process_test.cpp",
"properties_test.cpp",
"quick_exit_test.cpp",
"result_test.cpp",

View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* 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
#include <dirent.h>
#include <sys/types.h>
#include <iterator>
#include <memory>
#include <vector>
namespace android {
namespace base {
class AllPids {
class PidIterator {
public:
PidIterator(DIR* dir) : dir_(dir, closedir) { Increment(); }
PidIterator& operator++() {
Increment();
return *this;
}
bool operator==(const PidIterator& other) const { return pid_ == other.pid_; }
bool operator!=(const PidIterator& other) const { return !(*this == other); }
long operator*() const { return pid_; }
// iterator traits
using difference_type = pid_t;
using value_type = pid_t;
using pointer = const pid_t*;
using reference = const pid_t&;
using iterator_category = std::input_iterator_tag;
private:
void Increment();
pid_t pid_ = -1;
std::unique_ptr<DIR, decltype(&closedir)> dir_;
};
public:
PidIterator begin() { return opendir("/proc"); }
PidIterator end() { return nullptr; }
};
} // namespace base
} // namespace android

39
base/process.cpp Normal file
View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* 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 "android-base/process.h"
namespace android {
namespace base {
void AllPids::PidIterator::Increment() {
if (!dir_) {
return;
}
dirent* de;
while ((de = readdir(dir_.get())) != nullptr) {
pid_t pid = atoi(de->d_name);
if (pid != 0) {
pid_ = pid;
return;
}
}
pid_ = -1;
}
} // namespace base
} // namespace android

35
base/process_test.cpp Normal file
View file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* 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 "android-base/process.h"
#include <unistd.h>
#include <gtest/gtest.h>
TEST(process, find_ourselves) {
#if defined(__linux__)
bool found_our_pid = false;
for (const auto& pid : android::base::AllPids{}) {
if (pid == getpid()) {
found_our_pid = true;
}
}
EXPECT_TRUE(found_our_pid);
#endif
}