Why thread stuck? [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
I'm implementing a multiple threads download manager on Windows using C++.
The main thread starts download manage thread M, M starts several download threads D.
Each D will do the HTTP data transfer using library cpr which is a wrapper around libcurl.
After starts some D threads, M enters a loop, keep watching the download progress.
The strange thing: once the second D started, or I abort the first D by return error code(an integer other then 0, I return 1.) from the libcurl's CURLOPT_XFERINFOFUNCTION callback, M's loop will stop. (There's one debugging output inside M's loop. I notice its stop by the disappear of that output from console. Maybe it's not stop, just going into some waiting state instead...)
Both M and D thread are started by STL's std::thread.
Have been scratched by this problem a whole day. Any clue will be appreciated...
This is the M thread entrance:
void HttpDownloader1::MasterThreadFunc_()
{
int loop_count = 0;
// start the first download thread
if (!SplitDownload_(nullptr))
{
status_ = Status::ERRONEOUS;
return;
}
uint64_t prev_downloaded_bytes = recorder_->GetDownloadedBytes();
for (loop_count = 0; download_threads_.size() > 0; loop_count++)
//while (true)
{
loop_count++;
#ifdef _DEBUG
Debug_("main loop, threads: " + std::to_string(download_threads_.size()));
#endif
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 0.5s
DownloadThread* splitable_segment = nullptr;
auto it = download_threads_.begin();
while (it != download_threads_.end())
{
DownloadThread* thread = *it;
if (thread->status_ == Status::FINISH)
{
delete thread;
it = download_threads_.erase(it);
}
else
{
switch (thread->status_)
{
case Status::RUNNING:
default:
recorder_->MarkFinish(thread->begin_, thread->pos_ - 1);
// part of this segment may have been splited to other download thread
//thread->end_ = recorder_->GetSegmentEnd(thread->pos_);
break;
case Status::SUCCESSFUL:
if (recorder_->IsInitialized())
{
thread->CloseFile();
recorder_->MarkFinish(thread->begin_, thread->pos_ - 1);
}
else
{
if (!PrepareFile_(*it))
status_ = Status::ERRONEOUS;
}
splitable_segment = *it;
break;
case Status::ERRONEOUS:
if (++retry_ > kMaxHttpRetry)
{
status_ = Status::ERRONEOUS;
}
else
{
thread->CloseFile();
recorder_->MarkFailed(thread->pos_, thread->end_);
splitable_segment = *it;
}
break;
}
it++;
}
}
// break out if error occured
if (status_ == Status::ERRONEOUS)
{
break;
}
// if download completed
if (recorder_->IsFinish())
{
status_ = Status::SUCCESSFUL;
break;
}
// calculate download speed every 1 second
if ((loop_count & 1) == 1)
{
auto bytes = recorder_->GetDownloadedBytes();
bytes_per_second_ = bytes - prev_downloaded_bytes;
prev_downloaded_bytes = bytes;
}
// save progress info every 2 seconds
if ((loop_count & 3) == 3)
{
recorder_->Save();
}
// split download when any thread is available or every 4 seconds
if (splitable_segment || (loop_count & 7) == 7)
{
if (splitable_segment != nullptr)
SplitDownload_(splitable_segment);
else if (download_threads_.size() < max_threads_)
SplitDownload_(nullptr);
}
}
master_thread_.detach();
status_ = status_ != Status::ERRONEOUS ? Status::SUCCESSFUL : status_;
}
This is how M start D thread:
bool HttpDownloader1::SplitDownload_(DownloadThread* thread)
{
if (!recorder_->IsInitialized())
{
if (!thread)
thread = CreateDownloadThread_();
thread->begin_ = 0;
thread->end_ = 0;
}
else
{
int64_t begin, end;
if (recorder_->GetTask(&begin, &end))
{
// initialize this segment
if (!thread)
thread = CreateDownloadThread_();
thread->begin_ = begin;
thread->end_ = end;
thread->pos_ = thread->begin_;
if (thread->file_ == nullptr)
{
//errno_t e = fopen_s(&thread->file_, target_.GetPath().c_str(), "rb+");
thread->file_ = fopen(target_.GetPath().c_str(), "rb+");
//if (e == 0 && thread->file_)
if (thread->file_)
{
fseek(thread->file_, (long)thread->begin_, SEEK_SET);
}
else
{
thread->status_ = Status::ERRONEOUS;
return false;
}
}
}
else
{
// no more segment to download or split, remove this thread if it exists.
if (thread)
thread->status_ = Status::FINISH;
}
}
if (thread && thread->status_ != Status::FINISH)
{
thread->status_ = Status::RUNNING;
thread->thread_ = std::thread(&HttpDownloader1::DownloadThreadFunc_, this, thread);
thread->thread_.detach();
}
return true;
}
This is the D thread entrance:
void HttpDownloader1::DownloadThreadFunc_(DownloadThread* thread)
{
cpr::Response rsp;
if (thread->file_ == nullptr)
{
rsp = cpr::Get(
cpr::Url(target_.url_.c_str()),
cpr::ConnectTimeout(std::chrono::seconds(kConnectionTimeout)),
cpr::Timeout(std::chrono::seconds(kTransmitTimeout)),
cpr::VerifySsl(false),
cpr::Header{ { "Range", thread->GetRangeHeaderString().c_str() } },
cpr::CurlOption({ CURLOPT_NOPROGRESS, 1 }),
cpr::CurlOption({ CURLOPT_WRITEDATA, nullptr }),
cpr::CurlOption({ CURLOPT_WRITEFUNCTION, &HttpDownloader1::WriteCallback_ })
);
}
else
{
rsp = cpr::Get(
cpr::Url(target_.url_.c_str()),
cpr::ConnectTimeout(std::chrono::seconds(kConnectionTimeout)),
cpr::Timeout(std::chrono::seconds(kTransmitTimeout)),
cpr::VerifySsl(false),
cpr::Header{ { "Range", thread->GetRangeHeaderString().c_str() } },
cpr::CurlOption({ CURLOPT_NOPROGRESS, 0 }),
cpr::CurlOption({ CURLOPT_XFERINFODATA, thread }),
cpr::CurlOption({ CURLOPT_XFERINFOFUNCTION, &HttpDownloader1::ProgressCallback_ }),
cpr::CurlOption({ CURLOPT_WRITEDATA, thread->file_ }),
cpr::CurlOption({ CURLOPT_WRITEFUNCTION, fwrite })
);
}
if (rsp.status_code == 0)
{
thread->status_ = Status::ERRONEOUS;
Log_("thread:" + std::to_string(thread->id_) + " error: HTTP status code 0");
}
else if (rsp.status_code >= 400)
{
thread->status_ = Status::ERRONEOUS;
Log_("thread:" + std::to_string(thread->id_) + " erorr: HTTP status code " + std::to_string(rsp.status_code));
}
else if (rsp.error.code != cpr::ErrorCode::OK)
{
thread->status_ = Status::ERRONEOUS;
Log_("thread:" + std::to_string(thread->id_) + "error: " + rsp.error.message);
}
else
{
if (thread->file_ == nullptr)
thread->response_header_ = rsp.header;
thread->status_ = Status::SUCCESSFUL;
}
}
This is libcurl's progress callback:
int HttpDownloader1::ProgressCallback_(
void* clientp, std::uint64_t dltotal, std::uint64_t dlnow, std::uint64_t ultotal, std::uint64_t ulnow
) {
auto thread = (DownloadThread*)clientp;
if (dlnow > 0)
{
thread->pos_ = thread->begin_ + dlnow;
if (thread->pos_ > thread->end_)
return 1;
}
return 0;
}

Answer: Because I made a stupid mistake...
Details:
The M thread didn't got stuck(halt abnormally), it's just in a dead loop.
The loop isn't in the main loop of M, but inside the recorder_->MarkFinish(...) call, where I forgot incrementing the iterator at one of the if branch when loop a list container by while(...) {...}.
So when I placed a breakpoint at the recorder_->MarkFinish() line, it wouldn't be caught.
How I found that eventually:
I don't have much experience at multiple thread programming. After scratching my head for nearly a whole day, I thought there must be some low level details unfamiliar to me. So I post this question.
#Raymond comments brought back my confidence. I begun to add debug outputs line by line inside the M thread's main loop trying to find out what it was doing when it seemed stuck. And noticed that each time the error occurred, the outputs would disappear right after that recorder_->MarkFinish(...) call. So I went into that function and caught the carelessly code bellow:
while (it != segments_.end())
{
Segment& seg = *it;
if (seg.begin_ > end) break;
if (seg.end_ < start) continue; // !
if (start <= seg.begin_ && seg.begin_ <= end)
seg.begin_ = end + 1;
if (start <= seg.end_ && seg.end_ <= end)
seg.end_ = start - 1;
if (seg.end_ < seg.begin_)
it = segments_.erase(it);
else
it++;
}
Hope this might help reducing some of the mysterious sense about the problem you meet.💀

Related

Schedular issue C++ windows

I have a scheduler code to perform some task as per given time.
I have a table in database of name config, where different time is given to every row which have time in second to read data from a different table. I gave time in the format like.
20 , 40, 50, 60 seconds.
Code should run in such a way that when I start my program after every 20 second that column should execute which have 20 second, after every 40 second that column should execute which have 40 second and so on. But it is not executing in that way. Scheduler is not working as per given seconds, it is skipping and mismatching time
Below is a code where I am trying to read data as per time given in config table
void plac::worker_thread(void)
{
try {
std::chrono::steady_clock::time_point tick_time = std::chrono::steady_clock::now();
std::uint32_t tick_count = 1;
plac::scheduling_struct scheduling_struct;
bool executing_backlog;
bool tick_iteration_complete = true;
std::uint32_t current_iteration;
while (1)
{
executing_backlog = false;
if (not this->scheduler_backlog.empty())
{
{
std::lock_guard<std::mutex> lck(this->mtx2);
current_iteration = this->scheduler_backlog.front();
this->scheduler_backlog.pop();
}
//executing_backlog = true;
}
if (not executing_backlog and tick_iteration_complete) {
//tick_time = std::chrono::steady_clock::now();
//std::this_thread::sleep_until(tick_time + std::chrono::milliseconds(1000)); //1 second delay
tick_time = std::chrono::steady_clock::now();
std::this_thread::sleep_until(std::chrono::steady_clock::now() + std::chrono::milliseconds(1000)); //1 second delay
tick_iteration_complete = false;
if (++tick_count > this->scan_rate_max)
tick_count = 1;
}
{
std::lock_guard<std::mutex> lck(this->mtx1);
if (not executing_backlog)
{
current_iteration = this->scheduler_iteration;
if (++this->scheduler_iteration >= this->scheduler_list.size())
this->scheduler_iteration = 0;
}
scheduling_struct = this->scheduler_list.at(current_iteration);
}
if (tick_count % scheduling_struct.scan_rate == 0)
{
//std::cout << "hello" << std::endl;
if (this->_plac.find(scheduling_struct.ip) == this->_plac.end())
{
std::string error = fmt::format("No recored found in map at location {}", scheduling_struct.ip);
#ifdef _DEBUG
spdlog::error(error);
#endif // _DEBUG
LOG_ERROR << error;
continue;
}
if (not this->client.at(this->_plac.at(scheduling_struct.ip).client_location).read_progress)
{
const plac_common::config_struct config = this->_plac.at(scheduling_struct.ip).read_vector.at(scheduling_struct.config_serial_no);
if (not this->read_data(scheduling_struct))
{
spdlog::error("read data failed");
}
continue;
//this->read_data(current_iteration, client_location, config.area_type, config.area_number, config.read_location, config.read_length, config.word_length);
}
else
{
std::lock_guard<std::mutex> lck(this->mtx2);
this->scheduler_backlog.push(current_iteration);
}
}
tick_iteration_complete = true;
}
}
catch (const std::exception& ex) {
#ifdef _DEBUG
spdlog::error("Exception in worker thread. Exception : {}", ex.what());
#endif // _DEBUG
LOG_ERROR << ex.what();
}
}
OS - Windows 10 64 bit Home
Visual Studio - 15.9.19
Database - PostgreSQL
I think it maybe that if (++tick_count > this->scan_rate_max) causes that problem. When ++tick_count, it leads to change tick_count from 1 to 2. So, tick_count in if (tick_count % scheduling_struct.scan_rate == 0) is bigger than expected. I suggest that you can try to change ++tick_count to tick_count++.
if (not executing_backlog and tick_iteration_complete) {
//tick_time = std::chrono::steady_clock::now();
//std::this_thread::sleep_until(tick_time + std::chrono::milliseconds(1000)); //1 second delay
tick_time = std::chrono::steady_clock::now();
std::this_thread::sleep_until(std::chrono::steady_clock::now() + std::chrono::milliseconds(1000)); //1 second delay
tick_iteration_complete = false;
if (tick_count++ > this->scan_rate_max)
tick_count = 1;
}

SIM800L + Arduino TCP disconnect issue

Okay so I am currently using an arduino-uno to send AT commands to a SIM800l module. I am running a basic TCP socket server on my computer and the SIM800L is initially able to connect to it fine and send a message. After a seemingly random period of time on my serial monitor "NUL" is then displayed at which I am unable to send messages.
(So it is working initially however it seems to suddenly just stop mid process)
bool connectionProcedure()
{
bool result = false;
if(sendATcommand("AT+CIPSHUT", "SHUT OK", 200) == 1)
{
Serial.println("Proceed: AT+CIPMUX=0");
if(sendATcommand("AT+CIPMUX=0", "OK", 1000) == 1 )
{
Serial.println("Proceed: AT+CGATT=1");
if(sendATcommand("AT+CGATT=1", "OK", 1000) == 1 )
{
Serial.println("Proceed: AT+CSTT=\"gifgaff.com\",\"gifgaff\"");
if(sendATcommand("AT+CSTT=\"gifgaff.com\",\"gifgaff\"", "OK", 1000) == 1 )
{
Serial.println("Proceed: AT+CIICR");
if(sendATcommand("AT+CIICR", "OK", 60000) == 1 )
{
Serial.println("Proceed: AT+CIFSR");
if(sendATcommand("AT+CIFSR", ".", 5000) == 1 )
{
Serial.println("Process Success!");
result = true;
}
else
{
Serial.println("Error: AT+CIFSR");
}
}
else
{
Serial.println("Error: AT+CIICR");
}
}
else
{
Serial.println("Error: AT+CSTT=\"gifgaff.com\",\"gifgaff\"");
}
}
else
{
Serial.println("Error: AT+CGATT=1");
}
}
else
{
Serial.println("Error: AT+CIPMUX=0");
}
}
else
{
Serial.println("Error: CIPSHUT");
}
return result;
}
void awaitGSMConnection()
{
while( sendATcommand2("AT+CREG?", "+CREG: 0,1", "+CREG: 0,5", 1000) == 0 );
}
void initTCPConnection()
{
unsigned long previous;
unsigned int timeout = 10000;
Serial.println("Starting TCP Connection!");
if(sendATcommand("AT+CIPSTART=\"TCP\"," + tcpIp + "," + tcpPort, "OK", 10000) == 1)
{
Serial.println("Connection Success: Checking for stable connection before handshake!");
String expected = "CLOSED";
uint8_t x=0, answer=0;
char response[100];
memset(response, '\0', 100);
while( mySerial.available() > 0) mySerial.read();
x = 0;
previous = millis();
// Loop waits for the response from SIM800L
do {
if(mySerial.available() != 0) {
response[x] = mySerial.read();
x++;
// check if the desired answer 1 is in the response of the module
if (strstr(response, expected.c_str()) != NULL)
{
answer = 1;
}
}
}
while((answer == 0) && ((millis() - previous) < timeout));
if(answer == 0)
{
Serial.println("No Apparent ISSUE sending handshake!");
if(sendATcommand("AT+CIPSEND", ">", 4000) == 1)
{
Serial.println("SEND-HANDSHAKE");
sendMessage("Handshake");
//sendATcommand("AT+CIPCLOSE","OK",2000);
}
else
{
Serial.println("Error: AT+CIPSEND");
}
}
else
{
Serial.println("Connection test failed: Attempting to RECONNECT!");
}
}
else
{
Serial.println("Connection Error!");
}
}
Serial Monitor - Output
Here is the "NUL" I am talking about, this seems to appear completely randomly sometime during the connection. Random messages being sent from me from the server and being received.
No Apparent ISSUE sending handshake!
AT+CIPSEND
>
SEND-HANDSHAKE
Handshake␚
SEND OK
HELLO
AWESOME
COOL
INSANE
STILL WORKING!!!!
␀
Thanks in advance!

Escaping trapflag/single step

I'm writing a program that traces the execution of other programs. I'm using dynamic instruction instrumentation to track the behavior of x86's CMP instruction.
I'm using the windows debugging api to control the behavior of the debugged program. I start the program with the 'debug only this process' flag, and then set the trap flag on the main thread.
I then enter the main debugging loop:
bool cDebugger::ProcessNextDebugEvent(bool Verbose)
{
bool Result = true;
DEBUG_EVENT Event = { 0 };
DWORD Status = DBG_CONTINUE;
if (!WaitForDebugEvent(&Event, INFINITE))
{
_Reporter("Error: WaitForDebugEvent: " + to_string(GetLastError()));
return Result;
}
else
{
if (Event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Created process: " + GetFilenameFromHandle(Event.u.CreateProcessInfo.hFile));
}
else if (Event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Dll: " + GetFilenameFromHandle(Event.u.LoadDll.hFile) + " loaded at: " + to_string((unsigned int)Event.u.LoadDll.lpBaseOfDll));
_Dlls.insert(make_pair((unsigned int)Event.u.LoadDll.lpBaseOfDll, GetFilenameFromHandle(Event.u.LoadDll.hFile)));
}
else if (Event.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Thread[" + to_string(Event.dwThreadId) + "] created at: " + to_string((unsigned int)Event.u.CreateThread.lpStartAddress));
_Threads.push_back(Event.dwThreadId);
}
else if (Event.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Thread[" + to_string(Event.dwThreadId) + "] exited with: " + to_string(Event.u.ExitThread.dwExitCode));
auto It = std::find(_Threads.begin(), _Threads.end(), Event.dwThreadId);
if (It != _Threads.end())
_Threads.erase(It);
}
else if (Event.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Dll " + _Dlls[(unsigned int)Event.u.UnloadDll.lpBaseOfDll] + " unloaded at : " + to_string((unsigned int)Event.u.UnloadDll.lpBaseOfDll));
}
else if (Event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Process exited with: " + to_string(Event.u.ExitProcess.dwExitCode));
Result = false;
_Threads.clear();
}
else if (Event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
{
if (Event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
{
Status = DBG_EXCEPTION_HANDLED;
}
else
{
Status = DBG_EXCEPTION_NOT_HANDLED;
}
}
for (size_t i = 0; i < _Threads.size(); i++)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, _Threads[i]);
if (hThread == NULL)
{
_Reporter("Error: Failed to open thread: " + to_string(GetLastError()));
}
else
{
CONTEXT ThreadContext = GetThreadContext(hThread);
ProcessStep(ThreadContext, hThread);
ThreadContext.EFlags |= 0x100; // Set trap flag.
SetThreadContext(hThread, ThreadContext);
CloseHandle(hThread);
}
}
if (!ContinueDebugEvent(Event.dwProcessId, Event.dwThreadId, Status))
{
_Reporter("Error: ContinueDebugEvent: " + to_string(GetLastError()));
}
}
return Result;
}
As you can see I loop through all threads at the end of the function to make sure that the single-step exception will trigger on every next instruction in every thread.
However sometimes execution seems to 'escape' this trap, often executing millions of instructions before being caught again by the next debugging event.
I wrote another small application to test the behavior of my program:
int main(int argc, char* argv[])
{
//__asm int 3h
if (argc == 41234123)
{
printf("Got one\n");
}
return 0;
}
The expected output of the tracer should be:
0xDEADBEEF CMP 1 41234123
However somehow the tracer does not record this instruction (indicating that no debug event was raised, and that the trap flag was not set).
Can anybody see if I'm doing something wrong in my debug loop? Or what kind of behavior of the test program (loading of a dll) could be responsible for this?
The problem had something to do with code entering kernel space when calling windows apis. My solution was to set the page protection of the executable section of the test program to PAGE_GUARD:
SYSTEM_INFO Info;
GetSystemInfo(&Info);
DWORD StartAddress = (DWORD)Info.lpMinimumApplicationAddress;
DWORD StopAddress = (DWORD)Info.lpMaximumApplicationAddress;
DWORD PageSize = 0;
PageSize = Info.dwPageSize;
_Sections.clear();
for (DWORD AddressPointer = StartAddress; AddressPointer < StopAddress; AddressPointer += PageSize)
{
MEMORY_BASIC_INFORMATION Buffer;
VirtualQueryEx(_Process.GetHandle(), (LPCVOID)AddressPointer, &Buffer, sizeof(Buffer));
if (CheckBit(Buffer.Protect, 4) || CheckBit(Buffer.Protect, 5) || CheckBit(Buffer.Protect, 6) || CheckBit(Buffer.Protect, 7))
{
if (Buffer.State == MEM_COMMIT)
{
_Sections.push_back(make_pair((unsigned int)Buffer.BaseAddress, (unsigned int)Buffer.RegionSize));
AddressPointer = (unsigned int)Buffer.BaseAddress + (unsigned int)Buffer.RegionSize;
}
}
}
void cDebugger::SetPageGuard()
{
for (size_t i = 0; i < _Sections.size(); i++)
{
DWORD Dummy;
VirtualProtectEx(_Process.GetHandle(), (LPVOID)_Sections[i].first, _Sections[i].second, PAGE_GUARD | PAGE_EXECUTE_READWRITE, &Dummy);
}
}
This way I regain control because the system will fire a EXCEPTION_GUARD_PAGE when execution returns to a guarded page.
if (Event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
{
Status = DBG_CONTINUE;
if (!_Tracing)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, Event.dwThreadId);
CONTEXT ThreadContext = GetThreadContext(hThread);
if (ThreadContext.Eip == _EntryAddress)
{
ClearHardwareBreakpoint(0, hThread);
_Tracing = true;
}
CloseHandle(hThread);
}
SetPageGuard();
_Guarded = true;
}
else if (Event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
{
Status = DBG_CONTINUE;
}
else if (Event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_GUARD_PAGE)
{
Status = DBG_CONTINUE; // fires when processor lands on guarded pages
}
else
{
Status = DBG_EXCEPTION_NOT_HANDLED;
}
This solution is not perfect. There are possibly still some situations under which execution can still escape the 'trap'. But it solved my most immediate problem (being able to see the comparisons in my test program).

libusb_get_device_list seg fault

I am writing a file explorer application in Qt C++ and have a libUSB function (QList UsbDevice::getDeviceList()) which gets all attached USB devices, checks each one for my products vendor and product ID's, claims them and the returns them in an array. This all works fine and I get the device I want, however I have added a refresh button which should update the device list shown in a drop-down list (it basically calls the getDeviceList function again) but it seg faults when calling:
int numDevices = libusb_get_device_list(NULL, &usbDevices);
the second time around and I can't for the life of me see why. If someone could check over the code below and see if I have missed something stupid that would be very helpful.
QList<UsbDevice*> UsbDevice::getDeviceList()
{
unsigned char manf[256] = {'\0'};
QList<UsbDevice*> usbDeviceList;
libusb_device **usbDevices;
struct libusb_device_descriptor desc;
int numDevices = libusb_get_device_list(NULL, &usbDevices);
if(numDevices < 0)
{
libusb_free_device_list(usbDevices, 1);
return usbDeviceList;
}
QString error;
for(int i=0; i!=numDevices; ++i)
{
libusb_device *dev = usbDevices[i];
libusb_get_device_descriptor(dev, &desc);
if((desc.idVendor != VendorUsbId) && (desc.idProduct != ProductUsbId))
continue;
libusb_device_handle *handle = NULL;
libusb_config_descriptor *conf_desc = NULL;
int result = 0;
result = libusb_open(dev, &handle);
if(result < 0)
{
if(result == -3)
{
}
error = QString(libusb_error_name(result));
continue;
}
int config = 1;
if( handle == NULL)
{
continue;
}
result = libusb_set_configuration(handle, config);
if(result < 0)
{
error = QString(libusb_error_name(result));
continue;
}
result = libusb_get_config_descriptor(dev, 0, &conf_desc);
if(result < 0)
{
error = QString(libusb_error_name(result));
continue;
}
result = libusb_claim_interface(handle, 0);
if(result < 0)
{
error = QString(libusb_error_name(result));
continue;
}
result = libusb_get_string_descriptor_ascii(handle, desc.iProduct, manf, sizeof(manf));
if(result < 0)
{
error = QString(libusb_error_name(result));
continue;
}
UsbDevice *newDevice = new UsbDevice();
newDevice->setDeviceName(QString((char*)manf));
newDevice->setHandle(handle);
usbDeviceList << newDevice;
}
libusb_free_device_list(usbDevices, 1);
return usbDeviceList;
}
You are calling libusb_init() at the beginning of your program, but you are also calling libusb_exit() at the beginning : before calling a.exec().
Your first call probably happens in MainWindow constructor ?
You could instead subclass QApplication, call libusb_init() in the constructor and libusb_exit() in the destructor.

fopen, fprintf and fclose forces socket connection end

I have a dll which hooks recv function of a network application. The code works just fine (it makes everything its suppossed to do), but if i add output logs to a file, the connection closes after some time working (the server side application throws the error "An existing connection was forcibly closed by the remote host").
That time isnt even always the same, sometimes it closes almost when initializing connection, other times i can use the connection for few secs before it gets closed. It does not give any error or warning message. If i remove the log code, the application runs fine. Any idea why is that happening? I run it in windows 8 x64
Also, even erasing the log code, the connection keeps being closed in windows xp x32.
Here is the recv hook code:
int __stdcall NewRecv(SOCKET socket, char *data, int datalen, int flags) {
int result = 0;
if(!IsLoginServerPacket(&socket)) {
INT size = 0,opcode = 0,temp = 0,writer = 0,second_op = 0;
do {
size = 0;
second_op = 0;
temp = 0;
writer = 0;
while(temp < 2) {
temp += recvPacket(socket,recv_gs_buffer+writer,2 - temp,flags);
writer += temp;
}
size = (*(SHORT*)recv_gs_buffer) & 0xffff;
// THIS IS THE LOG CODE
FILE *f = fopen("debug.txt", "a");
fprintf(f, "datalen=%d, size=%d\n", datalen, size);
fclose(f);
while(temp < size) {
temp += recvPacket(socket,recv_gs_buffer+writer,size - temp,flags);
writer += temp;
}
Decrypt(&gs_crypt,recv_gs_buffer+2,size-2);
opcode = (*(recv_gs_buffer+2) & 0xff);
if(opcode == EXTENDED_PROTOCOL) {
second_op = *(SHORT*)(recv_gs_buffer + 3);
second_op &= 0xffff;
HandleGameServerPacket(second_op,recv_gs_buffer+2,size-2);
}
} while(second_op == 0x8a || second_op == 0x8b);
if(opcode == 0x00) {
SetKey(recv_gs_buffer+4,&gs_crypt);
SetKey(recv_gs_buffer+4,&client_crypt);
} else
Crypt(&client_crypt,recv_gs_buffer+2,size-2);
int i = 0;
while(i < size) {
data[i] = recv_gs_buffer[i];
i++;
}
//memcpy(data,recv_gs_buffer,size);
result = size;
} else
result = recvPacket(socket,data,datalen,flags);
return result;
}
I just found the problem and its solution.
The injected app was configuring sockets on non blocking mode. Any little delay was making it throwing WSAEWOULDBLOCK (10035 error code). All i had to do to fix it was to retry the recv request if i get any error
INT val = 0;
while(temp < 2) {
val = recvPacket(socket,recv_gs_buffer+writer,2 - temp,flags);
if(val > 0) {
temp += val;
writer += temp;
}
}
And
val = 0;
while(temp < size) {
val = recvPacket(socket,recv_gs_buffer+writer,size - temp,flags);
if(val > 0) {
temp += val;
writer += temp;
}
}