activemq-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dusan Kutnik (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (AMQCPP-564) OS thread handles are kept forever
Date Wed, 18 Feb 2015 14:47:11 GMT

    [ https://issues.apache.org/jira/browse/AMQCPP-564?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14325947#comment-14325947
] 

Dusan Kutnik edited comment on AMQCPP-564 at 2/18/15 2:46 PM:
--------------------------------------------------------------

I implemented following methods in the Threading namespace:

////////////////////////////////////////////////////////////////////////////////
void Threading::releaseCurrentThreadHandle() {
    ThreadHandle* self = (ThreadHandle*)PlatformThread::getTlsValue(library->selfKey);

    if (self != NULL) {
        detachFromCurrentThread(self);
    }
}

////////////////////////////////////////////////////////////////////////////////
void Threading::detachFromCurrentThread(ThreadHandle* self) {

    PlatformThread::lockMutex(library->globalLock);

    // Destroy given Foreign Thread Facade that was created during runtime.
    std::vector<Thread*>::iterator iter = library->osThreads.begin();
	bool isFound = false;
    for (; iter != library->osThreads.end(); ++iter) {
		if (self->parent == *iter) {
			isFound = true;
			break;
		}
    }
	if (isFound)  {
		PlatformThread::setTlsValue(library->threadKey, NULL);
		PlatformThread::setTlsValue(library->selfKey, NULL);

		// Ensure all of this thread's local values are purged.
		threadExitTlsCleanup(self);

		// Destroy OS thread including self thread handle.
		delete *iter;

		// Remove thread form the global list.
		library->osThreads.erase(iter);
	}

	PlatformThread::unlockMutex(library->globalLock);
}

Both methods are static, the method void Threading::releaseCurrentThreadHandle() is public
and I am using it in the destructor of my thread object. It seems that the code runs correctly
at least on Windows. I will continue testing it on Linux and Solaris. I encountered no memory
leaks, but it would be nice, if someone could check the correctness of the implementation.
If it's correct, could you add these or similar methods to a future release of the library?


was (Author: duku):
I implemented following methods in the Threading namespace:

////////////////////////////////////////////////////////////////////////////////
void Threading::releaseCurrentThreadHandle() {
    ThreadHandle* self = (ThreadHandle*)PlatformThread::getTlsValue(library->selfKey);

    if (self != NULL) {
        detachFromCurrentThread(self);
    }
}

////////////////////////////////////////////////////////////////////////////////
void Threading::detachFromCurrentThread(ThreadHandle* self) {

    PlatformThread::lockMutex(library->globalLock);

    // Destroy given Foreign Thread Facade that was created during runtime.
    std::vector<Thread*>::iterator iter = library->osThreads.begin();
	bool isFound = false;
    for (; iter != library->osThreads.end(); ++iter) {
		if (self->parent == *iter) {
			isFound = true;
			break;
		}
    }
	if (isFound)  {
		PlatformThread::setTlsValue(library->threadKey, NULL);
		PlatformThread::setTlsValue(library->selfKey, NULL);

		// Ensure all of this thread's local values are purged.
		threadExitTlsCleanup(self);

		// Remove thread form the global list.
		library->osThreads.erase(iter);

		// Destroy OS thread including self thread handle.
		delete self->parent;
	}

	PlatformThread::unlockMutex(library->globalLock);
}

Both methods are static, the method void Threading::releaseCurrentThreadHandle() is public
and I am using it in the destructor of my thread object. It seems that the code runs correctly
at least on Windows. I will continue testing it on Linux and Solaris. I encountered no memory
leaks, but it would be nice, if someone could check the correctness of the implementation.
If it's correct, could you add these or similar methods to a future release of the library?

> OS thread handles are kept forever
> ----------------------------------
>
>                 Key: AMQCPP-564
>                 URL: https://issues.apache.org/jira/browse/AMQCPP-564
>             Project: ActiveMQ C++ Client
>          Issue Type: Improvement
>          Components: Decaf
>    Affects Versions: 3.8.3
>         Environment: All
>            Reporter: Dusan Kutnik
>            Assignee: Timothy Bish
>
> The method decaf::internal::util::concurrent::Threading::attachToCurrentThread() creates
a proxy thread object for a new OS thread and keeps it in a vector:
> ////////////////////////////////////////////////////////////////////////////////
> ThreadHandle* Threading::attachToCurrentThread() {
>     Pointer<ThreadHandle> thread(initThreadHandle(new ThreadHandle()));
>     thread->handle = PlatformThread::getCurrentThread();
>     thread->state = Thread::RUNNABLE;
>     thread->stackSize = PlatformThread::getStackSize(thread->handle);
>     thread->name = ::strdup(
>         std::string(std::string("OS-Thread") + Integer::toString(library->osThreadId.getAndIncrement())).c_str());
>     thread->threadId = PlatformThread::getCurrentThreadId();
>     // An OS Thread doesn't have a running thread, this is only a proxy to only one ref.
>     thread->references = 1;
>     // Now create a Decaf Thread as a proxy to the OS thread.
>     Pointer<Thread> osThread(new Thread(thread.get()));
>     thread->parent = osThread.get();
>     thread->osThread = true;
>     PlatformThread::setTlsValue(library->threadKey, osThread.get());
>     PlatformThread::setTlsValue(library->selfKey, thread.get());
>     // Store the Thread that wraps this OS thread for later deletion since
>     // no other owners exist.
>     PlatformThread::lockMutex(library->globalLock);
>     library->osThreads.push_back(osThread.release());
>     PlatformThread::unlockMutex(library->globalLock);
>     return thread.release();
> }
> This method is part of the mutex machinery in the AMQ CPP. The only way how to free this
memory is to invoke the method decaf::internal::util::concurrent::Threading::shutdown(). In
our scenario we create continuously new worker threads that communicate with ActiveMQ broker.
This leads to the situation that new OS thread handles are still being created and never freed.
The consumed RAM is rapidly growing since the size of the thread object is on our platform
(Win 64bit) 1632 Bytes. We would need to have possibility to explicitly free this OS thread
object before it terminates, for instance something like:
> void decaf::internal::util::concurrent::Threading::detachFromCurrentThread()
> Is there a reasonable workaround or another way how to free this OS thread?



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Mime
View raw message