Merge commit '99163ff431a23938a6060d7c8268a5a1e8571310'

Conflicts:
	td/telegram/MessagesManager.cpp
This commit is contained in:
Andrea Cavalli 2020-10-02 17:34:08 +02:00
commit 6a3a55f244
10 changed files with 93 additions and 84 deletions

View File

@ -6,6 +6,7 @@
// //
#include "td/utils/benchmark.h" #include "td/utils/benchmark.h"
#include "td/utils/common.h"
#include "td/utils/crypto.h" #include "td/utils/crypto.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
@ -185,7 +186,7 @@ class AesCtrOpenSSLBench : public td::Benchmark {
void run(int n) override { void run(int n) override {
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, key.raw, iv.raw); EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), nullptr, key.raw, iv.raw);
td::MutableSlice data_slice(data, DATA_SIZE); td::MutableSlice data_slice(data, DATA_SIZE);
td::AesCtrState state; td::AesCtrState state;

View File

@ -13770,7 +13770,9 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
bool is_creator = (channel.flags_ & CHANNEL_FLAG_USER_IS_CREATOR) != 0; bool is_creator = (channel.flags_ & CHANNEL_FLAG_USER_IS_CREATOR) != 0;
if (is_creator) { if (is_creator) {
return DialogParticipantStatus::Creator(!has_left, false, string()); bool is_anonymous = channel.admin_rights_ != nullptr &&
(channel.admin_rights_->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
return DialogParticipantStatus::Creator(!has_left, is_anonymous, string());
} else if (channel.admin_rights_ != nullptr) { } else if (channel.admin_rights_ != nullptr) {
return get_dialog_participant_status(false, std::move(channel.admin_rights_), string()); return get_dialog_participant_status(false, std::move(channel.admin_rights_), string());
} else if (channel.banned_rights_ != nullptr) { } else if (channel.banned_rights_ != nullptr) {

View File

@ -13,7 +13,6 @@
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
#include "td/utils/tl_helpers.h"
namespace td { namespace td {

View File

@ -266,7 +266,7 @@ void Global::add_location_access_hash(double latitude, double longitude, int64 a
location_access_hashes_[get_location_key(latitude, longitude)] = access_hash; location_access_hashes_[get_location_key(latitude, longitude)] = access_hash;
} }
double get_server_time() { double get_global_server_time() {
return G()->server_time(); return G()->server_time();
} }

View File

@ -450,6 +450,6 @@ inline Global *G_impl(const char *file, int line) {
return static_cast<Global *>(context); return static_cast<Global *>(context);
} }
double get_server_time(); double get_global_server_time();
} // namespace td } // namespace td

View File

@ -10238,6 +10238,7 @@ void MessagesManager::delete_all_channel_messages_from_user_on_server(ChannelId
int32 MessagesManager::get_unload_dialog_delay() const { int32 MessagesManager::get_unload_dialog_delay() const {
constexpr int32 DIALOG_UNLOAD_DELAY = 60; // seconds constexpr int32 DIALOG_UNLOAD_DELAY = 60; // seconds
constexpr int32 DIALOG_UNLOAD_BOT_DELAY = 1800; // seconds constexpr int32 DIALOG_UNLOAD_BOT_DELAY = 1800; // seconds
CHECK(is_message_unload_enabled()); CHECK(is_message_unload_enabled());
auto default_unload_delay = td_->auth_manager_->is_bot() ? DIALOG_UNLOAD_BOT_DELAY : DIALOG_UNLOAD_DELAY; auto default_unload_delay = td_->auth_manager_->is_bot() ? DIALOG_UNLOAD_BOT_DELAY : DIALOG_UNLOAD_DELAY;
return narrow_cast<int32>(G()->shared_config().get_option_integer("message_unload_delay", default_unload_delay)); return narrow_cast<int32>(G()->shared_config().get_option_integer("message_unload_delay", default_unload_delay));
@ -12600,6 +12601,8 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
<< ", flags = " << flags << " for " << message_id << " in " << dialog_id; << ", flags = " << flags << " for " << message_id << " in " << dialog_id;
is_outgoing = supposed_to_be_outgoing; is_outgoing = supposed_to_be_outgoing;
/*
// it is useless to call getChannelsDifference, because the channel pts will be increased already
if (dialog_type == DialogType::Channel && !running_get_difference_ && !running_get_channel_difference(dialog_id) && if (dialog_type == DialogType::Channel && !running_get_difference_ && !running_get_channel_difference(dialog_id) &&
get_channel_difference_to_log_event_id_.count(dialog_id) == 0) { get_channel_difference_to_log_event_id_.count(dialog_id) == 0) {
// it is safer to completely ignore the message and re-get it through getChannelsDifference // it is safer to completely ignore the message and re-get it through getChannelsDifference
@ -12609,6 +12612,7 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
return {DialogId(), nullptr}; return {DialogId(), nullptr};
} }
} }
*/
} }
MessageId reply_to_message_id = message_info.reply_to_message_id; MessageId reply_to_message_id = message_info.reply_to_message_id;
@ -15990,15 +15994,24 @@ Result<FullMessageId> MessagesManager::get_top_thread_full_message_id(DialogId d
if (m->message_id.is_scheduled()) { if (m->message_id.is_scheduled()) {
return Status::Error(400, "Message is scheduled"); return Status::Error(400, "Message is scheduled");
} }
if (m->reply_info.is_comment) { if (dialog_id.get_type() != DialogType::Channel) {
return Status::Error(400, "Chat can't have message threads");
}
if (!m->reply_info.is_empty() && m->reply_info.is_comment) {
if (!is_visible_message_reply_info(dialog_id, m)) { if (!is_visible_message_reply_info(dialog_id, m)) {
return Status::Error(400, "Message has no comments"); return Status::Error(400, "Message has no comments");
} }
return FullMessageId{DialogId(m->reply_info.channel_id), m->linked_top_thread_message_id}; return FullMessageId{DialogId(m->reply_info.channel_id), m->linked_top_thread_message_id};
} else { } else {
if (!m->top_thread_message_id.is_valid() || !is_visible_message_reply_info(dialog_id, m)) { if (!m->top_thread_message_id.is_valid()) {
return Status::Error(400, "Message has no thread"); return Status::Error(400, "Message has no thread");
} }
if (!m->message_id.is_server()) {
return Status::Error(400, "Message thread is unavailable for the message");
}
if (!td_->contacts_manager_->get_channel_has_linked_channel(dialog_id.get_channel_id())) {
return Status::Error(400, "Message threads are unavailable in the chat");
}
return FullMessageId{dialog_id, m->top_thread_message_id}; return FullMessageId{dialog_id, m->top_thread_message_id};
} }
} }

View File

@ -6,6 +6,7 @@
// //
#include "td/telegram/UpdatesManager.h" #include "td/telegram/UpdatesManager.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.hpp" #include "td/telegram/telegram_api.hpp"
#include "td/telegram/AnimationsManager.h" #include "td/telegram/AnimationsManager.h"

View File

@ -10,7 +10,6 @@
#include "td/telegram/ChatId.h" #include "td/telegram/ChatId.h"
#include "td/telegram/DialogId.h" #include "td/telegram/DialogId.h"
#include "td/telegram/PtsManager.h" #include "td/telegram/PtsManager.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h" #include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h" #include "td/telegram/UserId.h"

View File

@ -36,7 +36,7 @@ void store_time(double time_at, StorerT &storer) {
} else { } else {
double time_left = max(time_at - Time::now(), 0.0); double time_left = max(time_at - Time::now(), 0.0);
store(time_left, storer); store(time_left, storer);
store(get_server_time(), storer); store(get_global_server_time(), storer);
} }
} }

View File

@ -21,34 +21,38 @@
#include "td/utils/tests.h" #include "td/utils/tests.h"
#include "td/utils/Time.h" #include "td/utils/Time.h"
#if TD_PORT_POSIX && !TD_THREAD_UNSUPPORTED
#include <algorithm>
#include <atomic> #include <atomic>
#include <set> #include <mutex>
using namespace td; #include <pthread.h>
#include <signal.h>
#endif
TEST(Port, files) { TEST(Port, files) {
CSlice main_dir = "test_dir"; td::CSlice main_dir = "test_dir";
rmrf(main_dir).ignore(); td::rmrf(main_dir).ignore();
ASSERT_TRUE(FileFd::open(main_dir, FileFd::Write).is_error()); ASSERT_TRUE(td::FileFd::open(main_dir, td::FileFd::Write).is_error());
ASSERT_TRUE(walk_path(main_dir, [](CSlice name, WalkPath::Type type) { UNREACHABLE(); }).is_error()); ASSERT_TRUE(td::walk_path(main_dir, [](td::CSlice name, td::WalkPath::Type type) { UNREACHABLE(); }).is_error());
mkdir(main_dir).ensure(); td::mkdir(main_dir).ensure();
mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "A").ensure(); td::mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "A").ensure();
mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "B").ensure(); td::mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "B").ensure();
mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "B" << TD_DIR_SLASH << "D").ensure(); td::mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "B" << TD_DIR_SLASH << "D").ensure();
mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "C").ensure(); td::mkdir(PSLICE() << main_dir << TD_DIR_SLASH << "C").ensure();
ASSERT_TRUE(FileFd::open(main_dir, FileFd::Write).is_error()); ASSERT_TRUE(td::FileFd::open(main_dir, td::FileFd::Write).is_error());
std::string fd_path = PSTRING() << main_dir << TD_DIR_SLASH << "t.txt"; td::string fd_path = PSTRING() << main_dir << TD_DIR_SLASH << "t.txt";
std::string fd2_path = PSTRING() << main_dir << TD_DIR_SLASH << "C" << TD_DIR_SLASH << "t2.txt"; td::string fd2_path = PSTRING() << main_dir << TD_DIR_SLASH << "C" << TD_DIR_SLASH << "t2.txt";
auto fd = FileFd::open(fd_path, FileFd::Write | FileFd::CreateNew).move_as_ok(); auto fd = td::FileFd::open(fd_path, td::FileFd::Write | td::FileFd::CreateNew).move_as_ok();
auto fd2 = FileFd::open(fd2_path, FileFd::Write | FileFd::CreateNew).move_as_ok(); auto fd2 = td::FileFd::open(fd2_path, td::FileFd::Write | td::FileFd::CreateNew).move_as_ok();
fd2.close(); fd2.close();
int cnt = 0; int cnt = 0;
const int ITER_COUNT = 1000; const int ITER_COUNT = 1000;
for (int i = 0; i < ITER_COUNT; i++) { for (int i = 0; i < ITER_COUNT; i++) {
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) { td::walk_path(main_dir, [&](td::CSlice name, td::WalkPath::Type type) {
if (type == WalkPath::Type::NotDir) { if (type == td::WalkPath::Type::NotDir) {
ASSERT_TRUE(name == fd_path || name == fd2_path); ASSERT_TRUE(name == fd_path || name == fd2_path);
} }
cnt++; cnt++;
@ -56,28 +60,28 @@ TEST(Port, files) {
} }
ASSERT_EQ((5 * 2 + 2) * ITER_COUNT, cnt); ASSERT_EQ((5 * 2 + 2) * ITER_COUNT, cnt);
bool was_abort = false; bool was_abort = false;
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) { td::walk_path(main_dir, [&](td::CSlice name, td::WalkPath::Type type) {
CHECK(!was_abort); CHECK(!was_abort);
if (type == WalkPath::Type::EnterDir && ends_with(name, PSLICE() << TD_DIR_SLASH << "B")) { if (type == td::WalkPath::Type::EnterDir && ends_with(name, PSLICE() << TD_DIR_SLASH << "B")) {
was_abort = true; was_abort = true;
return WalkPath::Action::Abort; return td::WalkPath::Action::Abort;
} }
return WalkPath::Action::Continue; return td::WalkPath::Action::Continue;
}).ensure(); }).ensure();
CHECK(was_abort); CHECK(was_abort);
cnt = 0; cnt = 0;
bool is_first_dir = true; bool is_first_dir = true;
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) { td::walk_path(main_dir, [&](td::CSlice name, td::WalkPath::Type type) {
cnt++; cnt++;
if (type == WalkPath::Type::EnterDir) { if (type == td::WalkPath::Type::EnterDir) {
if (is_first_dir) { if (is_first_dir) {
is_first_dir = false; is_first_dir = false;
} else { } else {
return WalkPath::Action::SkipDir; return td::WalkPath::Action::SkipDir;
} }
} }
return WalkPath::Action::Continue; return td::WalkPath::Action::Continue;
}).ensure(); }).ensure();
ASSERT_EQ(6, cnt); ASSERT_EQ(6, cnt);
@ -85,13 +89,13 @@ TEST(Port, files) {
ASSERT_EQ(12u, fd.write("Hello world!").move_as_ok()); ASSERT_EQ(12u, fd.write("Hello world!").move_as_ok());
ASSERT_EQ(4u, fd.pwrite("abcd", 1).move_as_ok()); ASSERT_EQ(4u, fd.pwrite("abcd", 1).move_as_ok());
char buf[100]; char buf[100];
MutableSlice buf_slice(buf, sizeof(buf)); td::MutableSlice buf_slice(buf, sizeof(buf));
ASSERT_TRUE(fd.pread(buf_slice.substr(0, 4), 2).is_error()); ASSERT_TRUE(fd.pread(buf_slice.substr(0, 4), 2).is_error());
fd.seek(11).ensure(); fd.seek(11).ensure();
ASSERT_EQ(2u, fd.write("?!").move_as_ok()); ASSERT_EQ(2u, fd.write("?!").move_as_ok());
ASSERT_TRUE(FileFd::open(main_dir, FileFd::Read | FileFd::CreateNew).is_error()); ASSERT_TRUE(td::FileFd::open(main_dir, td::FileFd::Read | td::FileFd::CreateNew).is_error());
fd = FileFd::open(fd_path, FileFd::Read | FileFd::Create).move_as_ok(); fd = td::FileFd::open(fd_path, td::FileFd::Read | td::FileFd::Create).move_as_ok();
ASSERT_EQ(13u, fd.get_size().move_as_ok()); ASSERT_EQ(13u, fd.get_size().move_as_ok());
ASSERT_EQ(4u, fd.pread(buf_slice.substr(0, 4), 1).move_as_ok()); ASSERT_EQ(4u, fd.pread(buf_slice.substr(0, 4), 1).move_as_ok());
ASSERT_STREQ("abcd", buf_slice.substr(0, 4)); ASSERT_STREQ("abcd", buf_slice.substr(0, 4));
@ -102,81 +106,73 @@ TEST(Port, files) {
} }
TEST(Port, SparseFiles) { TEST(Port, SparseFiles) {
CSlice path = "sparse.txt"; td::CSlice path = "sparse.txt";
unlink(path).ignore(); td::unlink(path).ignore();
auto fd = FileFd::open(path, FileFd::Write | FileFd::CreateNew).move_as_ok(); auto fd = td::FileFd::open(path, td::FileFd::Write | td::FileFd::CreateNew).move_as_ok();
ASSERT_EQ(0, fd.get_size().move_as_ok()); ASSERT_EQ(0, fd.get_size().move_as_ok());
int64 offset = 100000000; td::int64 offset = 100000000;
fd.pwrite("a", offset).ensure(); fd.pwrite("a", offset).ensure();
ASSERT_EQ(offset + 1, fd.get_size().move_as_ok()); ASSERT_EQ(offset + 1, fd.get_size().move_as_ok());
auto real_size = fd.get_real_size().move_as_ok(); auto real_size = fd.get_real_size().move_as_ok();
if (real_size >= offset + 1) { if (real_size >= offset + 1) {
LOG(ERROR) << "File system doesn't support sparse files, rewind during streaming can be slow"; LOG(ERROR) << "File system doesn't support sparse files, rewind during streaming can be slow";
} }
unlink(path).ensure(); td::unlink(path).ensure();
} }
TEST(Port, Writev) { TEST(Port, Writev) {
std::vector<IoSlice> vec; td::vector<td::IoSlice> vec;
CSlice test_file_path = "test.txt"; td::CSlice test_file_path = "test.txt";
unlink(test_file_path).ignore(); td::unlink(test_file_path).ignore();
auto fd = FileFd::open(test_file_path, FileFd::Write | FileFd::CreateNew).move_as_ok(); auto fd = td::FileFd::open(test_file_path, td::FileFd::Write | td::FileFd::CreateNew).move_as_ok();
vec.push_back(as_io_slice("a")); vec.push_back(td::as_io_slice("a"));
vec.push_back(as_io_slice("b")); vec.push_back(td::as_io_slice("b"));
vec.push_back(as_io_slice("cd")); vec.push_back(td::as_io_slice("cd"));
ASSERT_EQ(4u, fd.writev(vec).move_as_ok()); ASSERT_EQ(4u, fd.writev(vec).move_as_ok());
vec.clear(); vec.clear();
vec.push_back(as_io_slice("efg")); vec.push_back(td::as_io_slice("efg"));
vec.push_back(as_io_slice("")); vec.push_back(td::as_io_slice(""));
vec.push_back(as_io_slice("hi")); vec.push_back(td::as_io_slice("hi"));
ASSERT_EQ(5u, fd.writev(vec).move_as_ok()); ASSERT_EQ(5u, fd.writev(vec).move_as_ok());
fd.close(); fd.close();
fd = FileFd::open(test_file_path, FileFd::Read).move_as_ok(); fd = td::FileFd::open(test_file_path, td::FileFd::Read).move_as_ok();
Slice expected_content = "abcdefghi"; td::Slice expected_content = "abcdefghi";
ASSERT_EQ(static_cast<int64>(expected_content.size()), fd.get_size().ok()); ASSERT_EQ(static_cast<td::int64>(expected_content.size()), fd.get_size().ok());
std::string content(expected_content.size(), '\0'); td::string content(expected_content.size(), '\0');
ASSERT_EQ(content.size(), fd.read(content).move_as_ok()); ASSERT_EQ(content.size(), fd.read(content).move_as_ok());
ASSERT_EQ(expected_content, content); ASSERT_EQ(expected_content, content);
} }
#if TD_PORT_POSIX && !TD_THREAD_UNSUPPORTED #if TD_PORT_POSIX && !TD_THREAD_UNSUPPORTED
#include <signal.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <algorithm>
#include <mutex>
static std::mutex m; static std::mutex m;
static std::vector<std::string> ptrs; static td::vector<td::string> ptrs;
static std::vector<int *> addrs; static td::vector<int *> addrs;
static TD_THREAD_LOCAL int thread_id; static TD_THREAD_LOCAL int thread_id;
static void on_user_signal(int sig) { static void on_user_signal(int sig) {
int addr; int addr;
addrs[thread_id] = &addr; addrs[thread_id] = &addr;
char ptr[10];
snprintf(ptr, 6, "%d", thread_id);
std::unique_lock<std::mutex> guard(m); std::unique_lock<std::mutex> guard(m);
ptrs.push_back(std::string(ptr)); ptrs.push_back(td::to_string(thread_id));
} }
TEST(Port, SignalsAndThread) { TEST(Port, SignalsAndThread) {
setup_signals_alt_stack().ensure(); td::setup_signals_alt_stack().ensure();
set_signal_handler(SignalType::User, on_user_signal).ensure(); td::set_signal_handler(td::SignalType::User, on_user_signal).ensure();
SCOPE_EXIT { SCOPE_EXIT {
set_signal_handler(SignalType::User, nullptr).ensure(); td::set_signal_handler(td::SignalType::User, nullptr).ensure();
}; };
std::vector<std::string> ans = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; td::vector<td::string> ans = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
{ {
std::vector<td::thread> threads; td::vector<td::thread> threads;
int thread_n = 10; int thread_n = 10;
std::vector<Stage> stages(thread_n); td::vector<td::Stage> stages(thread_n);
ptrs.clear(); ptrs.clear();
addrs.resize(thread_n); addrs.resize(thread_n);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
threads.emplace_back([&, i] { threads.emplace_back([&, i] {
setup_signals_alt_stack().ensure(); td::setup_signals_alt_stack().ensure();
if (i != 0) { if (i != 0) {
stages[i].wait(2); stages[i].wait(2);
} }
@ -193,13 +189,12 @@ TEST(Port, SignalsAndThread) {
CHECK(ptrs == ans); CHECK(ptrs == ans);
//LOG(ERROR) << ptrs; //LOG(ERROR) << ptrs;
//LOG(ERROR) << std::set<int *>(addrs.begin(), addrs.end()).size();
//LOG(ERROR) << addrs; //LOG(ERROR) << addrs;
} }
{ {
Stage stage; td::Stage stage;
std::vector<td::thread> threads; td::vector<td::thread> threads;
int thread_n = 10; int thread_n = 10;
ptrs.clear(); ptrs.clear();
addrs.resize(thread_n); addrs.resize(thread_n);
@ -208,7 +203,6 @@ TEST(Port, SignalsAndThread) {
stage.wait(thread_n); stage.wait(thread_n);
thread_id = i; thread_id = i;
pthread_kill(pthread_self(), SIGUSR1); pthread_kill(pthread_self(), SIGUSR1);
//kill(pid_t(syscall(SYS_gettid)), SIGUSR1);
}); });
} }
for (auto &t : threads) { for (auto &t : threads) {
@ -223,16 +217,16 @@ TEST(Port, SignalsAndThread) {
} }
TEST(Port, EventFdAndSignals) { TEST(Port, EventFdAndSignals) {
set_signal_handler(SignalType::User, [](int signal) {}).ensure(); td::set_signal_handler(td::SignalType::User, [](int signal) {}).ensure();
SCOPE_EXIT { SCOPE_EXIT {
set_signal_handler(SignalType::User, nullptr).ensure(); td::set_signal_handler(td::SignalType::User, nullptr).ensure();
}; };
std::atomic_flag flag; std::atomic_flag flag;
flag.test_and_set(); flag.test_and_set();
auto main_thread = pthread_self(); auto main_thread = pthread_self();
td::thread interrupt_thread{[&flag, &main_thread] { td::thread interrupt_thread{[&flag, &main_thread] {
setup_signals_alt_stack().ensure(); td::setup_signals_alt_stack().ensure();
while (flag.test_and_set()) { while (flag.test_and_set()) {
pthread_kill(main_thread, SIGUSR1); pthread_kill(main_thread, SIGUSR1);
td::usleep_for(1000 * td::Random::fast(1, 10)); // 0.001s - 0.01s td::usleep_for(1000 * td::Random::fast(1, 10)); // 0.001s - 0.01s
@ -242,7 +236,7 @@ TEST(Port, EventFdAndSignals) {
for (int timeout_ms : {0, 1, 2, 10, 100, 500}) { for (int timeout_ms : {0, 1, 2, 10, 100, 500}) {
double min_diff = 10000000; double min_diff = 10000000;
double max_diff = 0; double max_diff = 0;
for (int t = 0; t < max(5, 1000 / td::max(timeout_ms, 1)); t++) { for (int t = 0; t < td::max(5, 1000 / td::max(timeout_ms, 1)); t++) {
td::EventFd event_fd; td::EventFd event_fd;
event_fd.init(); event_fd.init();
auto start = td::Timestamp::now(); auto start = td::Timestamp::now();
@ -255,7 +249,7 @@ TEST(Port, EventFdAndSignals) {
} }
LOG_CHECK(min_diff >= 0) << min_diff; LOG_CHECK(min_diff >= 0) << min_diff;
LOG_CHECK(max_diff < 10) << max_diff; // LOG_CHECK(max_diff < 10) << max_diff;
LOG(INFO) << min_diff << " " << max_diff; LOG(INFO) << min_diff << " " << max_diff;
} }
flag.clear(); flag.clear();