Mutex locked ошибка

I am working a thread pool with work stealing capabilities, but whenever the program tries to lock the mutex in the work queue, I get an exception error.

I’ve tried the program on both Windows Visual Studio 2015 and Ubuntu 14.04 and both produce a run time exception.

I’ve tested the work queue extensively by itself and can’t reproduce the error. If I comment out the try_steal function, I do not run into any errors. Lastly I’ve replace std::mutex with std::recursive_mutex and I still get the same error.

I thought the exception occurred during the deconstruction of the thread pool, namely one thread trying to read the work queue of another thread that has been destroyed already. But even after the introduction of an infinite loop before the end of the program, the same exception occurred.

I was wondering if there was something else I was not thinking to check, below you will find the relevant code and the VS 2015 and Linux call stacks.

Thanks for all your help.

Windows Call stack:

msvcp140d.dll!mtx_do_lock(_Mtx_internal_imp_t * mtx, const xtime * target)
msvcp140d.dll!_Mtx_lock(_Mtx_internal_imp_t * mtx)
thread_pool_test.exe!std::_Mtx_lockX(_Mtx_internal_imp_t * _Mtx)
thread_pool_test.exe!std::_Mutex_base::lock()
thread_pool_test.exe!std::lock_guard::lock_guard(std::mutex & _Mtx)
thread_pool_test.exe!work_stealing_queue::try_steal(function_wrapper & res)
thread_pool_test.exe!thread_pool_steal::pop_task_from_other_thread_queue(function_wrapper & task)
thread_pool_test.exe!thread_pool_steal::run_pending_task()
thread_pool_test.exe!thread_pool_steal::worker_thread(unsigned int my_index_)
thread_pool_test.exe!std::_Invoker_pmf_pointer::_Call(void (unsigned int) * _Pmf, thread_pool_steal * && _Arg1, int && <_Args2_0>) Line 1373 C++
thread_pool_test.exe!std::invoke(void (unsigned int) * && _Obj, thread_pool_steal * && <_Args_0>, int && <_Args_1>)
thread_pool_test.exe!std::_LaunchPad,std::default_delete > > >::_Execute<0,1,2>(std::tuple & _Tup, std::integer_sequence __formal)
thread_pool_test.exe!std::_LaunchPad,std::default_delete > > >::_Run(std::_LaunchPad,std::default_delete > > > * _Ln)
thread_pool_test.exe!std::_LaunchPad,std::default_delete > > >::_Go()
thread_pool_test.exe!std::_Pad::_Call_func(void * _Data)
ucrtbased.dll!0fa27e48()
[Frames below may be incorrect and/or missing, no symbols loaded for ucrtbased.dll]
ucrtbased.dll!0fa27b8b()
kernel32.dll!@BaseThreadInitThunk@12 ()
ntdll.dll!___RtlUserThreadStart@8 ()
ntdll.dll!__RtlUserThreadStart@8 ()

Linux call stack:

[New Thread 0x7ffff6f5d700 (LWP 4395)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff6f5d700 (LWP 4395)]
__GI___pthread_mutex_lock (mutex=0x0)
    at ../nptl/pthread_mutex_lock.c:66
66  ../nptl/pthread_mutex_lock.c: No such file or directory.
(gdb) bt
#0  __GI___pthread_mutex_lock (mutex=0x0)
    at ../nptl/pthread_mutex_lock.c:66
#1  0x0000000000401f53 in __gthread_mutex_lock (__mutex=0x50)
    at /usr/include/x86_64-linux-gnu/c++/4.9/bits/gthr-default.h:748
#2  0x00000000004023ba in std::mutex::lock (this=0x50)
    at /usr/include/c++/4.9/mutex:135
#3  0x000000000040370a in std::lock_guard<std::mutex>::lock_guard (
    this=0x7ffff6f5cd10, __m=...) at /usr/include/c++/4.9/mutex:377
#4  0x00000000004030fa in work_stealing_queue::try_steal (this=0x0, 
    res=...) at Source.cpp:250
#5  0x00000000004032c8 in thread_pool_steal::pop_task_from_other_thread_queue (this=0x7fffffffdac0, task=...) at Source.cpp:302
#6  0x00000000004035e4 in thread_pool_steal::run_pending_task (
    this=0x7fffffffdac0) at Source.cpp:358
#7  0x00000000004031ba in thread_pool_steal::worker_thread (
    this=0x7fffffffdac0, my_index_=0) at Source.cpp:283
#8  0x000000000040d3d4 in std::_Mem_fn<void (thread_pool_steal::*)(unsigned int)>::operator()<int, void>(thread_pool_steal*, int&&) const (
    this=0x62af78, __object=0x7fffffffdac0)
    at /usr/include/c++/4.9/functional:569
#9  0x000000000040cec9 in std::_Bind_simple<std::_Mem_fn<void (thread_pool_steal::*)(unsigned int)> (thread_pool_steal*, int)>::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) (this=0x62af68)
    at /usr/include/c++/4.9/functional:1700
#10 0x000000000040c87f in std::_Bind_simple<std::_Mem_fn<void (thread_pool_steal::*)(unsigned int)> (thread_pool_steal*, int)>::operator()() (
    this=0x62af68) at /usr/include/c++/4.9/functional:1688
#11 0x000000000040c4ea in std::thread::_Impl<std::_Bind_simple<std::_Mem_fn<void (thread_pool_steal::*)(unsigned int)> (thread_pool_steal*, int)> >::_M_run() (this=0x62af50) at /usr/include/c++/4.9/thread:115
#12 0x00007ffff78f7e40 in ?? ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#13 0x00007ffff7bc4182 in start_thread (arg=0x7ffff6f5d700)
    at pthread_create.c:312
#14 0x00007ffff735e47d in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Code:

class work_stealing_queue
{
 private:
 typedef function_wrapper data_type;
 std::deque<data_type> the_queue;
 mutable std::mutex the_mutex;

bool empty() const
{
    std::lock_guard<std::mutex> lock(the_mutex);
    return the_queue.empty();
}

bool try_steal(data_type& res)
{
    std::lock_guard<std::mutex> lock(the_mutex);
    if (the_queue.empty())
    {
        return false;
    }

    res = std::move(the_queue.back());
    the_queue.pop_back();
    return true;
}
};


class thread_pool_steal
{

typedef function_wrapper task_type;

std::atomic_bool done;
threadsafe_queue<task_type> pool_work_queue;
std::vector<std::unique_ptr<work_stealing_queue> > queues;
std::vector<std::thread> threads;

static thread_local work_stealing_queue* local_work_queue;
static thread_local unsigned int my_index;

join_threads joiner;


bool pop_task_from_other_thread_queue(task_type& task)
{
    for (unsigned i = 0; i<queues.size(); ++i)
    {
        unsigned const index = (my_index + i + 1) % queues.size();
        if (queues[index]->try_steal(task))
        {
            return true;
        }
    }
    return false;
}

public:

thread_pool_steal() : done(false), joiner(threads)
{
    unsigned const thread_count = std::thread::hardware_concurrency();
    try
    {
        for (auto i = 0; i<thread_count; ++i)
        {
            queues.push_back(std::unique_ptr<work_stealing_queue>(std::make_unique<work_stealing_queue>()));
            threads.push_back(std::move(std::thread(&thread_pool_steal::worker_thread, this, i)));

        }
    }
    catch (...)
    {
        done = true;
        throw;
    }
};

~thread_pool_steal()
{
    done = true;
};

TLDR: Make sure you are not locking a mutex that has been destroyed / hasn’t been initialized.

Although the OP has his answer, I thought I would share my issue in case anyone else has the same problem I did.

Notice that the assertion is in __pthread_mutex_lock and not in the unlock. This, to me, suggests that most other people having this issue are not unlocking a mutex in a different thread than the one that locked it; they are just locking a mutex that has been destroyed.

For me, I had a class (Let’s call it Foo) that registered a static callback function with some other class (Let’s call it Bar). The callback was being passed a reference to Foo and would occasionally lock/unlock a mutex that was a member of Foo.

This problem occurred after the Foo instance was destroyed while the Bar instance was still using the callback. The callback was being passed a reference to an object that no longer existed and, therefore, was calling __pthread_mutex_lock on garbage memory.

Note, I was using C++11’s std::mutex and std::lock_guard<std::mutex>, but, since I was on Linux, the problem was exactly the same.

Я сталкиваюсь со следующей ошибкой в ​​непредсказуемое время в коммуникационном приложении на базе Linux (arm):

pthread_mutex_lock.c:82: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed.

Google выдает много ссылок на эту ошибку, но мало информации, имеющей отношение к моей ситуации. Мне было интересно, может ли кто-нибудь дать мне несколько идей о том, как устранить эту ошибку. Кто-нибудь знает общую причину этого утверждения?

Заранее спасибо.

person
Dave Causey
  
schedule
09.07.2009
  
source
источник


Ответы (8)

Непоколебимый 4 дня подряд. Я объявляю победу на этом. Ответ — «глупая ошибка пользователя» (см. комментарии выше). Мьютекс должен быть разблокирован только тем потоком, который его заблокировал. Спасибо, что терпели меня.

person
Dave Causey
  
schedule
13.07.2009

TLDR: убедитесь, что вы не блокируете мьютекс, который был уничтожен/не был инициализирован.

Хотя у ОП есть свой ответ, я подумал, что поделюсь своей проблемой на случай, если у кого-то еще возникнет та же проблема, что и у меня.

Обратите внимание, что утверждение находится в __pthread_mutex_lock, а не в разблокировке. Для меня это говорит о том, что большинство других людей, сталкивающихся с этой проблемой, не разблокируют мьютекс в другом потоке, чем тот, который его заблокировал; они просто блокируют мьютекс, который был уничтожен.

Для меня у меня был класс (назовем его Foo), который зарегистрировал статическую функцию обратного вызова с каким-то другим классом (назовем его Bar). Обратный вызов передавал ссылку на Foo и иногда блокировал/разблокировал мьютекс, который был членом Foo.

Эта проблема возникла после того, как экземпляр Foo был уничтожен, когда экземпляр Bar все еще использовал обратный вызов. Обратному вызову передавалась ссылка на объект, который больше не существует, и, следовательно, вызывал __pthread_mutex_lock для мусорной памяти.

Обратите внимание: я использовал std::mutex и std::lock_guard<std::mutex> из С++ 11, но, поскольку я работал в Linux, проблема была точно такой же.

person
rationalcoder
  
schedule
09.04.2017

Я столкнулся с той же проблемой, и Google отправил меня сюда. Проблема с моей программой заключалась в том, что в некоторых ситуациях я не инициализировал мьютекс перед его блокировкой.

Хотя утверждение в принятом ответе является законным, я думаю, что это не причина этого неудавшегося утверждения. Потому что об ошибке сообщается pthread_mutex_lockне разблокировка).

Также, как всегда, более вероятно, что ошибка находится в исходном коде программиста, а не в компиляторе.

person
Shayan Pooya
  
schedule
15.11.2011

Быстрый поиск в Google, который я сделал, часто обвиняет в этом неправильную оптимизацию компилятора. Подведение итогов можно найти здесь. Возможно, стоит взглянуть на вывод сборки, чтобы убедиться, что gcc создает правильный код.

Либо так, либо вам удается топать память, используемую библиотекой pthread… такие проблемы довольно сложно найти.

person
Chris Arguin
  
schedule
09.07.2009

у меня была такая же проблема

в моем случае внутри потока я подключал vertica db к odbc, добавляя следующие настройки в /etc/odbcinst.ini, что решило мою проблему. пока не получаю исключения.

[ODBC]
Threading = 1

кредиты: hynek

person
ismail
  
schedule
05.02.2015

Я только что пробился через это и подумал, что это может помочь другим. В моем случае проблема возникла в очень простом методе, который заблокировал мьютекс, проверил общую переменную и затем вернулся. Этот метод является переопределением базового класса, который создает рабочий поток.

Проблема в этом случае заключалась в том, что базовый класс создавал поток в конструкторе. Затем поток начал выполняться, и была вызвана реализация метода производных классов. К сожалению, производный класс еще не завершил построение, и мьютекс в производном классе имел неинициализированные данные в качестве владельца мьютекса. Из-за этого казалось, что он на самом деле заблокирован, когда это не так.

Решение действительно простое. Добавьте в базовый класс защищенный метод StartThread(). Это нужно вызывать в конструкторе производных классов, а не из базового класса.

person
ReefSmacker
  
schedule
23.07.2019

добавление Threading=0 в файл /etc/odbcinst.ini устранило эту проблему.

person
stanley emmanuel
  
schedule
14.09.2016

C++14 seems to have omitted a mechanism for checking whether an std::mutex is locked or not. See this SO question:

https://stackoverflow.com/questions/21892934/how-to-assert-if-a-stdmutex-is-locked

There are several ways around this, e.g. by using;

std::mutex::try_lock()
std::unique_lock::owns_lock()

But neither of these are particularly satisfying solutions.

try_lock() is permitted to return a false negative and has undefined behaviour if the current thread has locked the mutex. It also has side-effects. owns_lock() requires the construction of a unique_lock on top of the original std::mutex.

Obviously I could roll my own, but I’d rather understand the motivations for the current interface.

The ability to check the status of a mutex (e.g. std::mutex::is_locked()) does not seem like an esoteric request to me, so I suspect the Standard Committee deliberately omitted this feature rather than it being an oversight.

Why?

Edit: Ok so maybe this use case isn’t as common as I had expected, so I’ll illustrate my particular scenario. I have a machine learning algorithm which is distributed on multiple threads. Each thread operates asynchronously, and returns to a master pool once it has completed an optimisation problem.

It then locks a master mutex. The thread must then pick a new parent from which to mutate an offspring, but may only pick from parents which do not currently have offspring that are being optimised by other threads. I therefore need to perform a search to find parents that are not currently locked by another thread. There is no risk of the status of the mutex changing during the search, as the master thread mutex is locked. Obviously there’s other solutions (I’m currently using a boolean flag) but I thought the mutex offers a logical solution to this problem, as it exists for the purpose of inter-thread synchronization.

Community's user avatar

asked Sep 11, 2016 at 13:29

quant's user avatar

12

I can see at least two severe problems with the suggested operation.

The first one was already mentioned in a comment by @gnasher729:

You can’t really reasonably check whether a mutex is locked, because one nanosecond after the check it can get unlocked or locked. So if you wrote if (mutex_is_locked ()) … then mutex_is_locked could return the correct result, but by the time the if is executed, it is wrong.

The only way to be sure that the “is currently locked” property of a mutex doesn’t change is to, well, lock it yourself.

The second problem I see is that unless you lock a mutex, your thread doesn’t synchronize with the thread that had previously locked the mutex. Therefore, it isn’t even well-defined to speak about “before” and “after” and whether the mutex is locked or not is kind of asking whether Schrödiger’s cat is currently alive without attempting to open the box.

If I understand correctly, then both problems would be moot in your particular case thanks to the master mutex being locked. But this doesn’t seem like a particularly common case to me so I think that the committee did the right thing by not adding a function that might be somewhat useful in very special scenarios and cause damage in all others. (In the spirit of: “Make interfaces easy to use correctly and difficult to use incorrectly.”)

And if I may say, I think that the setup you currently have is not the most elegant and could be refactored to avoid the problem altogether. For example, instead of the master thread checking all potential parents for one that is not currently locked, why not maintain a queue of ready parents? If a thread wants to optimize another one, it pops the next one off the queue and as soon as it has new parents, it adds them to the queue. That way, you don’t even need the master thread as a coordinator.

Community's user avatar

answered Sep 11, 2016 at 14:22

5gon12eder's user avatar

5gon12eder5gon12eder

6,9662 gold badges23 silver badges29 bronze badges

7

It seems that you are using the secondary mutexes not to lock access to an optimisation problem, but to determine whether an optimisation problem is being optimised right now or not.

That is completely unnecessary. I’d have a list of problems that need optimising, a list of problems being optimised right now, and a list of problems that have been optimised. (Don’t take «list» literally, take it to mean «any appropriate data structure).

The operations of adding a new problem to the list of unoptimised problems, or moving a problem from one list to the next, would be done under protection of the single «master» mutex.

answered Sep 11, 2016 at 18:27

gnasher729's user avatar

gnasher729gnasher729

42.5k4 gold badges60 silver badges121 bronze badges

3

In addition to the two reasons given in 5gon12eder’s answer above, I’d like to add that it is neither necessary nor desirable.

If you are already holding a mutex, then you had better know that you’re holding it! You don’t need to ask. Just like with owning a block of memory or any other resource, you should know exactly whether or not you own it, and when it’s appropriate to release/delete the resource.
If that is not the case, your program is designed badly, and you are heading for trouble.

If you need to access the shared resource protected by the mutex, and you are not already holding the mutex, then you need to acquire the mutex. There’s no other option, otherwise your program logic is not correct.
You might find blocking acceptable or inacceptable, in either case lock() or try_lock() will give the behavior you want. All you need to know, positively, and without doubt, is whether you successfully acquired the mutex (the return value of try_lock tells you). It’s inconsequential whether someone else holds it or whether you got a spurious failure.

In every other case, bluntly, it’s none of your business. You don’t need to know, and you shouldn’t know, or make assumptions (for the timeliness and sync issues mentioned in the other question).

answered Sep 11, 2016 at 16:34

Damon's user avatar

DamonDamon

2531 silver badge3 bronze badges

5

As others said, there’s no use case where is_locked on a mutex is of any benefit, that’s why the function does not exist.

The case you’re having a problem with is incredibly common, it’s basically what worker threads do, which are one of the, if not the most common implementation of threads.

You have a shelf with 10 boxes on it. You have 4 workers working with these boxes. How do you make sure the 4 workers work on different boxes? The first worker takes a box off the shelf before they start working on it. The second worker sees 9 boxes on the shelf.

There are no mutexes to lock the boxes, so seeing the state of the imaginary mutex on the box is not necessary, and abusing a mutex as a boolean is just wrong. The mutex locks the shelf.

answered Sep 12, 2016 at 18:46

Peter's user avatar

PeterPeter

3,7181 gold badge12 silver badges20 bronze badges

4

I want to add a use-case for this: It would enable an internal function to ensure as a precondition / assertion that the caller is indeed holding the lock.

For classes with several such internal functions, and possibly many public functions calling them, it could ensure, that someone adding another public function calling the internal one did indeed acquire the lock.

class SynchronizedClass
{

public:

void publicFunc()
{
  std::lock_guard<std::mutex>(_mutex);

  internalFuncA();
}

// A lot of code

void newPublicFunc()
{
  internalFuncA(); // whops, forgot to acquire the lock
}


private:

void internalFuncA()
{
  assert(_mutex.is_locked_by_this_thread());

  doStuffWithLockedResource();
}

};

answered Aug 14, 2018 at 17:14

B3ret's user avatar

B3retB3ret

1192 bronze badges

1

You may be wanting to use atomic_flag with the default memory order. It doesn’t have data races and never throws exceptions like mutex does with multiple unlock calls (and aborts uncontrollably, I might add…). Alternatively, there is atomic (e.g. atomic[bool] or atomic[int] (with triangle brackets, not [])), which has nice functions like load and compare_exchange_strong.

answered Feb 19, 2017 at 23:35

Andrew's user avatar

AndrewAndrew

1096 bronze badges

My use case for also wanting is_locked() involves using mutexes for automatic cleanup by the OS if an application crashes.

Process #1:
1) takes mutex (to avoid multiple processes being a «master»)
2) sets information in shared memory
3) Normally, clears information
4) releases mutex

If process #1 crashes, the mutex is released by the OS, but the shared memory information remains.

Pocess #2 wants to validate the shared memory information, but it is not valid if the mutex is no longer set, but has no interest in being a «master».

answered Jan 27, 2020 at 22:29

codemeister's user avatar

2

  • Forum
  • Windows Programming
  • Crash on locking mutex

Crash on locking mutex

I’m trying to lock a C++11 mutex, but whenever I do this, I get

1
2
terminate called after throwing an instance of 'std::system_error'
  what():  Invalid argument

The try_lock is returning «0» before the call. The code works perfect on Ubuntu, but crashes on my Windows 10 partition.

I’m using MinGW W64 to compile. Any way to get rid of this crash?

Last edited on

When I tried to google information about this, I got a lot of results from people trying to compile bitcoin wallets under Windows :D

Can you post the smallest program you can create that generates the same error reliably? I’d like to try compiling it under Cygwin and see if the same thing happens, then again in Visual Studio Community to see if it happens there too. That would at least narrow the problem down a bit.

I tried to replicate it with

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <thread>
#include <mutex>
#include <stdio.h>


int main()
{
	std::mutex* lock = new std::mutex();
	printf("locking\n");
	lock->lock();
	printf("unlocking\n");
	lock->unlock();
	printf("done\n");
	delete lock;
	return 0;
}

but it ran fine. here is the minimum code that it crashes with, it a thread wrapper I’m writing

m.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <unistd.h>
#include "J118/Thread.h"

using namespace std;
using namespace J118;

class TestThread : public Thread
{
public:
	TestThread();
	void run();
};

TestThread::TestThread() : Thread()
{
	printf("Thread Created\n");
}

void TestThread::run()
{
	printf("Thread Started...\n");
	sleep(10);
	printf("Thread done\n");
}

int main()
{
	FILE* output = fopen("DEBUG.txt", "w");
	fprintf(output, "TEST\n");
	fclose(output);
	output = NULL;
	printf("TEST\n");
	Thread* t = new TestThread();
	t->start();
	printf("The thread is running...\n");
	t->join();
	//delete t;
	usleep(10000000);
	
	return 0;
}

src/Thread.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

#include "J118/Thread.h"


//TODO: Fix crash when deleting right after creation.
namespace J118
{
	
Thread::Thread()
{
	thread_handle = NULL;
	strcpy(thread_name,"Uknown");
	running = false;
}

Thread::Thread(const char* n)\
{
	thread_handle = NULL;
	strcpy(thread_name,n);
	running = false;
	data_lock = new std::mutex();
}
	
Thread::~Thread()
{
	printf("Deleting thread\n");
	//data_lock->lock();
	if(thread_handle != NULL)
	{
		//data_lock->unlock();
		printf("ID001\n");
		join();
		printf("ID002\n");
		//thread_handle->detach();
		delete thread_handle;
		thread_handle = NULL;
	}
	else
	{
		data_lock->unlock();
	}
		
	
	SAFE_DELETE(data_lock);
}
	
void Thread::runProxy(void* me)
{
	
	printf("In thread...\n");
	
	Thread* callee = (Thread*)me;
	printf("Casted\n");
	callee->running = true;
	//callee->data_lock->unlock(); // Unlocking after thread is started [ID001]
	callee->run();
	//printf("POINT %x\n",((void*)callee->thread_handle));
	//delete callee->thread_handle;
	//callee->thread_handle = NULL;
	callee->running = false;
}
	
	
void Thread::start()
{
	printf("SSSSS\n");
	if(thread_handle != NULL)
	{
		//throw ThreadRunningException();
		if(running)
		{
			printf("Oh no...\n");
			throw ThreadRunningException();
			return;
		}
		else
		{
			join();
			//thread_handle->detach();
			delete thread_handle;
			thread_handle = NULL;
		}
	}
	else
	{
		printf("Starting\n");
		//data_lock->lock(); //Locking to start the thread [ID001]
		thread_handle = new std::thread(runProxy,this);
		printf("started\n");
	}
	
	
	
}
	
void Thread::join()
{
	int result = data_lock->try_lock();
	printf("Try lock returned %d\n", result);
	data_lock->lock(); //----------------------------------------CRASHES HERE------------------------------------------------
	printf("LOCKED\n");
	if(thread_handle != NULL && thread_handle->joinable())
	{
		printf("ID003\n");
		thread_handle->join();
		printf("ID004\n");
		delete thread_handle;
		thread_handle = NULL;
		data_lock->unlock();
	}
	else
	{
		data_lock->unlock();
	}
	
}

const char* ThreadRunningException::what() const throw()
{
	return "Instance of thread already running";
}


	
}/* namespace J118 */

include/J118/Thread.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#pragma once

//Universal Includes
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <exception>
#include <thread>
#include <mutex>

//J118 Library Includ1es
#include <J118/UtilityMacros.h>

//OS Specific Includes
#ifdef __linux__
#include <pthread.h>
#elif _WIN32

#else
#error "Cant determain type system, Threads failed to build!"
#endif

#define J118_THREAD_NAME_LENGTH 16
namespace J118
{

class ThreadRunningException: public std::exception
{
public:
	virtual const char* what() const throw();
};
	

class Thread
{
	
	
private:
	std::thread* thread_handle;
	std::mutex* data_lock;
	
	
protected:
	char thread_name[J118_THREAD_NAME_LENGTH];
	bool running;
	virtual void run() = 0;
	static void runProxy(void* me);
public:
	~Thread();
	Thread();
	Thread(const char* n);
	void start();
	void join();
	
	
};
} /*namespace J118 */

include/J118/UtilityMacros.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

#define SAFE_DELETE(pointer)\
if( pointer != nullptr)\
{\
	delete pointer;\
	pointer = nullptr;\
}\

#define SAFE_DELETE_ARRAY(pointer)\
if( pointer != nullptr)\
{\
	delete [] pointer;\
	pointer = nullptr;\
}


#define SAFE_FILE_CLOSE(pointer)\
if( pointer != nullptr)\
{\
	fclose(pointer);\
	pointer = nullptr;\
}

and I compile it with
G++ -o m m.cpp .\src\Thread.cpp -I include -static-libstdc++ -g -l pthread

and the output I get is

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TEST
Thread Created
SSSSS
Starting
started
The thread is running...
Try lock returned 0
In tterminate called after throwing an instance of 'hstd::system_errorr'e
ad . what():  .Invalid argument.


This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Casted
Thread Started... 

I found the issue, I forgot to initialize the mutex in the default constructor. It’s always the simplest things.

Why are you creating your mutexes with new? If you had made it a regular variable (i.e. std::mutex data_lock;) you couldn’t have forgotten because it would be initialized automatically. The same could be said about your std::thread object.

Last edited on

Topic archived. No new replies allowed.

Понравилась статья? Поделить с друзьями:
  • Mt4 общая ошибка устранение
  • Multivac c100 ошибки
  • Must declare the scalar variable sql ошибка
  • Msz ge35va коды ошибок
  • Msz ge22va коды ошибок