LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-06-2006, 07:43 AM   #1
fnurx
LQ Newbie
 
Registered: Oct 2006
Location: Gothenburg, Sweden
Distribution: Ubuntu (desktop), Debian (server)
Posts: 2

Rep: Reputation: 0
Beginner with threads. Weird(?) problem


Just started with threads. And are now having a pretty strange problem/error. I's probably not strange at all, just me not understanding
Anyway, I would really appreciate if someone could help me with this.
Attached some code in wich the error occur.
First, there's a Thread class. It's not very big, just some basics. And then a Mutex class, pretty straight forward. I have then done a class (MutexTest) for testing the Mutex class. It has a getPtr() method that returns a pointer to an int. In the getPtr() method I have a little loop that sets the pointer to zero a few times, so if another thread wants to write to the pointer, the app segfaults. It works as I planned as long as I dont lock/unlock the mutex Last I have a class (ThreadTest) for testing the Tread class, that retrieves the pointer from a MutexTest class to write to - segfaulting the app (if no mutex is used). Now, the problem is that when i use a mutex, it still segfaults (the getPtr() returns zero). But just sometimes. And I have no idea why. If someone could help me pointing out what's wrong with my code I'd be very thankful.

Code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

class Thread {
	public:
		Thread(void) { }
		virtual ~Thread(void) { }

	public:
		virtual void run(void) { // Create and run thread
			int ret;
			pthread_attr_t attr;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
			ret = pthread_create(&_thread, &attr, Thread::entryPoint, static_cast<void*>(this));
			pthread_attr_destroy(&attr);
			//if(ret) throw Error("Could not create thread");
		}

		void wait(void) const {	pthread_join(_thread, 0); } // Join thread

	protected:
		virtual void exec(void) = 0; // Virtual method to override

	private:
		static void* entryPoint(void* pthis) { // Static entry for thread
			Thread* pt = static_cast<Thread*>(pthis);
			pt->exec();
			return 0;
		}

	private:
		pthread_t _thread;
};

class Mutex {
	public:
		Mutex(void) {
			pthread_mutex_init(&_mutex, 0);
		}

		virtual ~Mutex(void) {
			pthread_mutex_destroy(&_mutex);
		}

	public:
		void lock(void) {
			//printf("locking mutex..\n");
			pthread_mutex_lock(&_mutex);
			//printf("mutex locked\n");
		}

		void unlock(void) {
			//printf("unlocking mutex..\n");
			pthread_mutex_unlock(&_mutex);
			//printf("mutex unlocked\n");
		}

	private:
		pthread_mutex_t	_mutex;
};

class MutexTest {
	public:
		MutexTest() { _ptr = new int; }
		virtual ~MutexTest() { delete _ptr; }

	public:
		int* getPtr(void) {
			_mutex.lock();
			int* temp;
			temp = _ptr; // backup pointer
			for(int i = 0; i < 10; i++) {
				_ptr = 0; usleep(2); // set pointer to 0 a few times to generate segfault when set in ThreadTest class
			}
			_ptr = temp; // restore pointer
			_mutex.unlock();
			return _ptr;
		}

	private:
		Mutex _mutex;
		int* _ptr;
};

class ThreadTest : public Thread {
	public:
		ThreadTest() { }
		virtual ~ThreadTest() { }

	private:
		void exec(void) { // override exec from Thread class
			printf("entering thread: %u\n", (int)pthread_self());
			int* x;
			for(int i = 0; i < 10; i++) {
				//printf("i = %d\n", i);
				x = _mtest->getPtr(); // get pointer from MutexTest class
				//printf("x = %d\n", (int)x);
				*x = 1; // set pointer to generate segfault
				usleep(10); // sleep to let other ThreadTest object call getPtr() in MutexTest
			}
		}
	public:
		void setMutexTest(MutexTest* mtest) { // set MutexTest object to call getPtr() from
			_mtest = mtest;
		}
	private:
		MutexTest* _mtest;
};

int main(int argc, char** argv)
{
	MutexTest mutex_test;
	ThreadTest thread_test[2];

	for(int i = 0; i < 2; i++) {
		thread_test[i].setMutexTest(&mutex_test);
		thread_test[i].run();
	}
	thread_test[0].wait();
	thread_test[1].wait();

	return 0;
}
 
Old 10-06-2006, 08:24 AM   #2
95se
Member
 
Registered: Apr 2002
Location: Windsor, ON, CA
Distribution: Ubuntu
Posts: 740

Rep: Reputation: 32
Hello, I think your problem lies in MutexTest::getPtr() here:

Code:
_ptr = temp; // restore pointer
_mutex.unlock();
return _ptr;
Your problem is that you unlock, THEN return _ptr. The problem w/ this is that _ptr's value can change to 0 after "_mutex.unlock()", but before "return _ptr." What you have to do is assign _ptr to a local temporary variable, then return that, like this:

Code:
_ptr = temp; // restore pointer
temp = _ptr; // looks redundant doesn't it, but it gets the point across ;) 
_mutex.unlock();
return temp;

Last edited by 95se; 10-06-2006 at 08:26 AM.
 
Old 10-06-2006, 09:59 AM   #3
fnurx
LQ Newbie
 
Registered: Oct 2006
Location: Gothenburg, Sweden
Distribution: Ubuntu (desktop), Debian (server)
Posts: 2

Original Poster
Rep: Reputation: 0
Of course, why didn't I see that Just not used to that kind of thinking yet. Now it works perfectly. Thank you very much for your help, and fast too. You just made my day, and LQ my new favorite forum
 
Old 10-06-2006, 11:33 AM   #4
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Thats an interesting way of starting a thread but I would have to say I don't like it
I suppose you are going to inherit anytype of threading job from thread and run it using the virtual func. correct?
I would see a job as "has a" thread not "is a" thread and this would just mess up your thread starter.
I had the same sort of concerns awhile back and posted the answer I came up with on LQ which you may want to use or just look at it, the link to the source is broken due to fly by night free hosts but if you would like the source just email me using the LQ message feature and I'll bounce it over.
http://www.linuxquestions.org/questi...d.php?t=466807
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Threads Problem maritos Programming 1 11-28-2005 11:34 PM
Java threads listed using kill -3 does not contain all threads found using ps -auxww coneheed Programming 2 11-14-2005 08:57 AM
Weird, weird apache2 problem atheist Debian 1 09-17-2004 08:26 PM
Java Threads vs Native Threads rjmendez Programming 0 08-16-2004 05:58 AM
installation problem ( beginner Pleazzz help ) kalok_kala Linux From Scratch 2 07-31-2003 03:11 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:03 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration