GIF89a=( õ' 7IAXKgNgYvYx\%wh…hŽth%ˆs%—x¨}9®Œ©€&©‰%¶†(¹–.¹5·œD¹&Çš)ÇŸ5ǘ;Í£*È¡&Õ²)ׯ7×µ<Ñ»4ï°3ø‘HÖ§KͯT÷¨Yÿšqÿ»qÿÔFØ !ù ' !ÿ NETSCAPE2.0 , =( þÀ“pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§gª«ªE¯°¨¬ª±²Œ¹º¹E¾­”´ÂB¶¯ §Åȸ»ÑD¾¿Á•ÄÅ®° ÝH¾ÒLÀÆDÙ«D¶BÝïðÀ¾DÑÑÔTÌÍíH òGö¨A RÎڐ |¥ ٭&ºìE8œ¹kGÔAÞpx­a¶­ã R2XB®åE8I€Õ6Xî:vT)äžþÀq¦è³¥ì仕F~%xñ  4#ZÔ‰O|-4Bs‘X:= QÉ œš lºÒyXJŠGȦ|s hÏíK–3l7·B|¥$'7Jީܪ‰‡àá”Dæn=Pƒ ¤Òëí‰`䌨ljóá¯Éüv>á–Á¼5 ½.69ûϸd«­ºÀûnlv©‹ªîf{¬ÜãPbŸ  l5‘ޝpß ´ ˜3aÅùäI«O’ý·‘áÞ‡˜¾Æ‚ÙÏiÇÿ‹Àƒ #öó)pâš Þ½ ‘Ý{ó)vmÞü%D~ 6f s}ŃƒDØW Eþ`‡þ À…L8xá†ç˜{)x`X/> Ì}mø‚–RØ‘*|`D=‚Ø_ ^ð5 !_…'aä“OÚ—7âcð`D”Cx`ÝÂ¥ä‹éY¹—F¼¤¥Š?¡Õ™ n@`} lď’ÄÉ@4>ñd œ à‘vÒxNÃ×™@žd=ˆgsžG±æ ´²æud &p8Qñ)ˆ«lXD©øÜéAžHìySun jª×k*D¤LH] †¦§C™Jä–´Xb~ʪwStŽ6K,°£qÁœ:9ت:¨þªl¨@¡`‚ûÚ ».Û¬¯t‹ÆSÉ[:°=Š‹„‘Nåû”Ìî{¿ÂA ‡Rà›ÀÙ6úë°Ÿð0Ä_ ½;ÃϱîÉì^ÇÛÇ#Ëë¼ôº!±Ä˜íUîÅÇ;0L1óÁµö«p% AÀºU̬ݵ¼á%霼€‡¯Á~`ÏG¯»À× ­²± =4ªnpð3¾¤³¯­ü¾¦îuÙuµÙ®|%2ÊIÿür¦#0·ÔJ``8È@S@5ê¢ ö×Þ^`8EÜ]ý.뜃Âç 7 ú ȉÞj œ½Dç zý¸iþœÑÙûÄë!ˆÞÀl§Ïw‹*DçI€nEX¯¬¼ &A¬Go¼QföõFç°¯;é¦÷îŽêJ°îúôF5¡ÌQ|îúöXªæ»TÁÏyñêï]ê² o óÎC=öõ›ÒÓPB@ D×½œä(>èCÂxŽ`±«Ÿ–JЀ»Û á¤±p+eE0`ëŽ`A Ú/NE€Ø†À9‚@¤à H½7”à‡%B‰`Àl*ƒó‘–‡8 2ñ%¸ —€:Ù1Á‰E¸àux%nP1ð!‘ðC)¾P81lÑɸF#ˆ€{´âé°ÈB„0>±û °b¡Š´±O‚3È–Ù()yRpbµ¨E.Z‘D8ÊH@% òŒx+%Ù˜Æcü »¸˜fõ¬b·d`Fê™8èXH"ÉÈ-±|1Ô6iI, 2““¬$+](A*jÐ QTÂo‰.ÛU슬Œã„Ž`¯SN¡–¶Äåyše¯ª’­¬‚´b¦Éož œ)åyâ@Ì®3 ÎtT̉°&Ø+žLÀf"Ø-|žçÔ>‡Ðv¦Ðžì\‚ Q1)Ž@Žh#aP72”ˆ™¨$‚ !ù " , =( …7IAXG]KgNgYvYxR"k\%w]'}hŽth%ˆg+ˆs%—r.—m3šx3˜x¨}9®€&©€+¨‡7§‰%¶†(¹–.¹œD¹&ǘ;Í•&ײ)×»4ïÌ6ò§KÍ þ@‘pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§g «¬ E ±± ¨­¶°ººE Á´”·®C¬²§Ç¶Œ»ÓDÃÕƷ¯Ê±H½ºM×ÁGÚ¬D¶BËÁ½î½DÓôTÏÛßîG»ôõC×CÌ l&âž:'òtU³6ɹ#·Ø)€'Ü.6±&ëÍÈ» K(8p0N?!æ2"ÛˆNIJX>R¼ÐO‚M '¡¨2¸*Ÿþ>#n↠å@‚<[:¡Iïf’ ¤TÚ˘CdbÜÙ“[«ŽEú5MBo¤×@€`@„€Êt W-3 ¶Ÿ¡BíêäjIÝ…Eò9[T…$íêﯧ„…•s»Óȳ¹€ÅÚdc®UUρ#±Ùïldj?´í¼²`\ŽÁðÞu|3'ÖŒ]ë6 ¶S#²‡˜FKLÈ *N E´‘áäŠ$˜›eÄYD„ºq«.è촁ƒs \-ÔjA 9²õ÷å- üúM[Âx(ís÷ì®x€|í¡Ù’p¦‚ ŽkÛTÇDpE@WÜ ²Ç]kŠ1¨ þ€·Yb ÓÁ‰l°*n0 ç™—žzBdОu¾7ĉBl€â‰-ºx~|UåU‰  h*Hœ|e"#"?vpÄiŠe6^ˆ„+qâŠm8 #VÇá ‘å–ÄV„œ|Аè•m"сœn|@›U¶ÆÎž—Špb¥G¨ED”€±Úê2FÌIç? >Éxå Œ± ¡¤„%‘žjŸ‘ꄯ<Ìaà9ijÐ2˜D¦È&›†Z`‚å]wþ¼Â:ç6àB¤7eFJ|õÒ§Õ,¨äàFÇ®cS·Ê¶+B°,‘Þ˜ºNûãØ>PADÌHD¹æž«ÄÀnÌ¥}­#Ë’ë QÀÉSÌÂÇ2ÌXÀ{æk²lQÁ2«ÊðÀ¯w|2Í h‹ÄÂG€,m¾¶ë3ÐÙ6-´ÅE¬L°ÆIij*K½ÀÇqï`DwVÍQXœÚÔpeœ±¬Ñ q˜§Tœ½µƒ°Œìu Â<¶aØ*At¯lmEØ ü ôÛN[P1ÔÛ¦­±$ÜÆ@`ùåDpy¶yXvCAyåB`ŽD¶ 0QwG#¯ æš[^Äþ $ÀÓÝǦ{„L™[±úKÄgÌ;ï£S~¹ìGX.ôgoT.»åˆ°ùŸûù¡?1zö¦Ÿž:ÅgÁ|ìL¹ „®£œŠ‚à0œ]PÁ^p F<"•ç?!,ñ‡N4—…PÄ Á„ö¨Û:Tè@hÀ‹%táÿ:ø-žI<`þ‹p I….)^ 40D#p@ƒj4–؀:²‰1Øâr˜¼F2oW¼#Z†;$Q q” ‘ ÂK¦ñNl#29 !’F@¥Bh·ᏀL!—XFóLH‘Kh¤.«hE&JòG¨¥<™WN!€ÑÙÚˆY„@†>Œž19J" 2,/ &.GXB%ÌRÈ9B6¹W]’î×ÔW¥’IÎ$ ñ‹ÓŒE8YÆ ¼³™ñA5“à®Q.aŸB€&Ø©³ JÁ—! ¦t)K%tœ-¦JF bòNMxLôþ)ÐR¸Ð™‘ èÝ6‘O!THÌ„HÛ ‰ !ù ) , =( …AXKgNgYvYxR"k\%wh…hŽh%ˆg+ˆs%—r.—x3˜x¨}9®€&©€+¨Œ,©‡7§‰%¶†(¹–.¹5·&Çš)ǘ;Í•&×£*Ȳ)ׯ7×»4ï°3øÌ6ò‘HÖ§KÍ»Hó¯T÷¨Yÿ»qÿÇhÿ þÀ”pH,È¤rÉl:ŸÐ¨tJ­Z¯Ø¬vËíz¿à°xL.›Ïè´zÍn»ßð¸|N¯Ûïø¼~Ïïûÿ€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§g ª« E$±²¨ª­ · °²½$E$ÂÕ««D· Í ¿¦Ç¶¸ÌŒ¾³CÃÅÆ E ééH½MÛÂGâªD­ çBêêϾD²ÒaÀà€Š1r­ðÓ¤ ÔožzU!L˜C'¾yW½UGtäÇïÙllê0×àÂuGþ)AÀs[þ·xì ÁxO%ƒûX2ó—  P£n›R/¡ÑšHše+êDm?# —‘Ç£6¡8íJ¡ŸâDiäªM¥Ö„ôj“¬¹£5oQ7°- <‡ *´lãÓŒ2r/a!l)dÈ A™ÈE¢ôÔ͆…ð ;Ö˜c ¡%ß‚’Ùˆâ¸b½—pe~C"BíëÚHïeF2§æŠ8qb t_`urŠeü wÅu3êæPv§h•"ß`íÍxçLĹÜÖ3á  ~Öº“®›¸ÏMDfJÙ °„ÛµáWõ%§œ‚à©–‚X ÓØ)@®Ñ›Eþ´wëuÅSxb8y\mÖzœ¥§ZbºE—ÂLªÌw!y(>¡™wú=Ç|ÅÝs¢d €CÁW)HÜcC$€L Ä7„r.á\{)@ð` @ äXÈ$PD” `šaG:§æˆOˆ72EÐamn]ù"ŒcÊxÑŒ° &dR8`g«iÙŸLR!¦P …d’ä¡“¦ðÎTƒ¦ià|À _ ¥ Qi#¦Šg›Æ ›noMµ ›V ã£)p ç£ÎW…š=Âeªk§†j„ ´®1ß²sÉxéW«jšl|0¯B0Û, \jÛ´›6±¬¶C ÛíWþï|ëÙ‹¸ñzĸV {ì;Ýñn¼òVˆm³I¼³.Ðã¤PN¥ ²µ¼„µCã+¹ÍByî£Ñ¾HŸ›ëê 7ìYÆFTk¨SaoaY$Dµœìï¿Ã29RÈkt Çïfñ ÇÒ:ÀÐSp¹3ÇI¨â¥DZÄ ü9Ïýögñ½­uÔ*3)O‘˜Ö[_hv ,àî×Et Ÿé¶BH€ Õ[ü±64M@ÔSÌM7dÐl5-ÄÙU܍´©zߌ3Ô€3ž„ „ ¶ÛPô½5×g› êÚ˜kN„Ý…0Îj4€Ìë°“#{þÕ3S2çKÜ'ợlø¼Ú2K{° {Û¶?žm𸧠ËI¼nEò='êüóºè^üæÃ_Û=°óž‚ì#Oý¿Í'¡½áo..ÏYìnüñCœO±Áa¿¢Kô½o,üÄËbö²çºíï{ËC Ú— "”Ï{ËK ÍÒw„õ±Oz dÕ¨à:$ ƒô—«v»] A#ð «€¿šéz)Rx׿ˆ¥‚d``èw-îyÏf×K!ð€þ­Ð|ìPľ„=Ì`ý(f” 'Pa ¥ÐBJa%Ðâf§„%Š¡}FàáÝ×6>ÉäŠG"éŽè=ø!oа^FP¼Ø©Q„ÀCÙÁ`(Ž\ÄÝ® ©Â$<n@dÄ E#ììUÒI! ‚#lù‹`k¦ÐÇ'Rró’ZýNBÈMF Í[¤+‹ðɈ-áwj¨¥þ8¾rá ,VÂh„"|½œ=×G_¦Ñ™EØ 0i*%̲˜Æda0mV‚k¾)›;„&6 p>ÓjK “¦Ç# âDÂ:ûc?:R Ó¬fÞéI-Ì“•Ã<ä=™Ï7˜3œ¨˜c2ŒW ,ˆ”8(T™P‰F¡Jhç"‚ ; 403WebShell
403Webshell
Server IP : 172.67.177.218  /  Your IP : 216.73.216.66
Web Server : LiteSpeed
System : Linux premium229.web-hosting.com 4.18.0-553.45.1.lve.el8.x86_64 #1 SMP Wed Mar 26 12:08:09 UTC 2025 x86_64
User : akhalid ( 749)
PHP Version : 8.3.22
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/cpanel/ea-ruby27/src/passenger-release-6.0.23/src/cxx_supportlib/oxt/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/cpanel/ea-ruby27/src/passenger-release-6.0.23/src/cxx_supportlib/oxt//implementation.cpp
/*
 * OXT - OS eXtensions for boosT
 * Provides important functionality necessary for writing robust server software.
 *
 * Copyright (c) 2008-2017 Phusion Holding B.V.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include "tracable_exception.hpp"
#include "backtrace.hpp"
#include "initialize.hpp"
#include "macros.hpp"
#include "thread.hpp"
#include "spin_lock.hpp"
#include "detail/context.hpp"
#ifdef __linux__
	#include <sys/syscall.h>
#endif

#ifdef OXT_THREAD_LOCAL_KEYWORD_SUPPORTED
	#include <cassert>
	#include <sstream>
	#include <cstring>
#endif
#include <cstring>


namespace oxt {

using namespace std;
using namespace boost;


static global_context_t *global_context = NULL;


/*
 * boost::thread_specific_storage is pretty expensive. So we use the __thread
 * keyword whenever possible - that's almost free.
 */
#ifdef OXT_THREAD_LOCAL_KEYWORD_SUPPORTED
	static __thread thread_local_context_ptr *local_context = NULL;
	__thread void *thread_signature = NULL;

	static void
	init_thread_local_context_support() {
		/* Do nothing. */
	}

	void
	set_thread_local_context(const thread_local_context_ptr &ctx) {
		local_context = new thread_local_context_ptr(ctx);
	}

	static void
	free_thread_local_context() {
		delete local_context;
		local_context = NULL;
	}

	thread_local_context *
	get_thread_local_context() {
		if (OXT_LIKELY(local_context != NULL)) {
			return local_context->get();
		} else {
			return NULL;
		}
	}
#else
	/*
	 * This is a *pointer* to a thread_specific_ptr because, once
	 * we've created a thread_specific_ptr, we never want to destroy it
	 * in order to avoid C++'s global variable destruction. All kinds
	 * of cleanup code may depend on local_context and because global
	 * variable destruction order is undefined, we just want to keep
	 * this object alive until the OS cleans it up.
	 */
	static thread_specific_ptr<thread_local_context_ptr> *local_context = NULL;

	static void
	init_thread_local_context_support() {
		local_context = new thread_specific_ptr<thread_local_context_ptr>();
	}

	void
	set_thread_local_context(const thread_local_context_ptr &ctx) {
		if (local_context != NULL) {
			local_context->reset(new thread_local_context_ptr(ctx));
		}
	}

	static void
	free_thread_local_context() {
		if (local_context != NULL) {
			local_context->reset();
		}
	}

	thread_local_context *
	get_thread_local_context() {
		if (OXT_LIKELY(local_context != NULL)) {
			thread_local_context_ptr *pointer = local_context->get();
			if (OXT_LIKELY(pointer != NULL)) {
				return pointer->get();
			} else {
				return NULL;
			}
		} else {
			return NULL;
		}
	}
#endif


#ifdef OXT_BACKTRACE_IS_ENABLED

trace_point::trace_point(const char *_function, const char *_source, unsigned short _line,
	const char *_data)
	: function(_function),
	  source(_source),
	  line(_line),
	  m_detached(false),
	  m_hasDataFunc(false)
{
	thread_local_context *ctx = get_thread_local_context();
	if (OXT_LIKELY(ctx != NULL)) {
		spin_lock::scoped_lock l(ctx->backtrace_lock);
		ctx->backtrace_list.push_back(this);
	} else {
		m_detached = true;
	}
	u.data = _data;
}

trace_point::trace_point(const char *_function, const char *_source, unsigned short _line,
	DataFunction _dataFunc, void *_userData, bool detached)
	: function(_function),
	  source(_source),
	  line(_line),
	  m_detached(detached),
	  m_hasDataFunc(true)
{
	if (!detached) {
		thread_local_context *ctx = get_thread_local_context();
		if (OXT_LIKELY(ctx != NULL)) {
			spin_lock::scoped_lock l(ctx->backtrace_lock);
			ctx->backtrace_list.push_back(this);
		} else {
			m_detached = true;
		}
	}
	u.dataFunc.func = _dataFunc;
	u.dataFunc.userData = _userData;
}

trace_point::trace_point(const char *_function, const char *_source, unsigned short _line,
	const char *_data, const detached &detached_tag)
	: function(_function),
	  source(_source),
	  line(_line),
	  m_detached(true),
	  m_hasDataFunc(false)
{
	u.data = _data;
}

trace_point::~trace_point() {
	if (OXT_LIKELY(!m_detached)) {
		thread_local_context *ctx = get_thread_local_context();
		if (OXT_LIKELY(ctx != NULL)) {
			spin_lock::scoped_lock l(ctx->backtrace_lock);
			assert(!ctx->backtrace_list.empty());
			ctx->backtrace_list.pop_back();
		}
	}
}

void
trace_point::update(const char *source, unsigned short line) {
	this->source = source;
	this->line = line;
}


tracable_exception::tracable_exception() {
	thread_local_context *ctx = get_thread_local_context();
	if (OXT_LIKELY(ctx != NULL)) {
		spin_lock::scoped_lock l(ctx->backtrace_lock);
		vector<trace_point *>::const_iterator it, end = ctx->backtrace_list.end();

		backtrace_copy.reserve(ctx->backtrace_list.size());
		for (it = ctx->backtrace_list.begin(); it != end; it++) {
			trace_point *p;
			if ((*it)->m_hasDataFunc) {
				p = new trace_point(
					(*it)->function,
					(*it)->source,
					(*it)->line,
					(*it)->u.dataFunc.func,
					(*it)->u.dataFunc.userData,
					true);
			} else {
				p = new trace_point(
					(*it)->function,
					(*it)->source,
					(*it)->line,
					(*it)->u.data,
					trace_point::detached());
			}
			backtrace_copy.push_back(p);
		}
	}
}

tracable_exception::tracable_exception(const tracable_exception &other)
	: std::exception()
{
	vector<trace_point *>::const_iterator it, end = other.backtrace_copy.end();
	backtrace_copy.reserve(other.backtrace_copy.size());
	for (it = other.backtrace_copy.begin(); it != end; it++) {
		trace_point *p;
		if ((*it)->m_hasDataFunc) {
			p = new trace_point(
				(*it)->function,
				(*it)->source,
				(*it)->line,
				(*it)->u.dataFunc.func,
				(*it)->u.dataFunc.userData,
				true);
		} else {
			p = new trace_point(
				(*it)->function,
				(*it)->source,
				(*it)->line,
				(*it)->u.data,
				trace_point::detached());
		}
		backtrace_copy.push_back(p);
	}
}

tracable_exception::tracable_exception(const no_backtrace &tag)
	: std::exception()
{
	// Do nothing.
}

tracable_exception::~tracable_exception() throw() {
	vector<trace_point *>::iterator it, end = backtrace_copy.end();
	for (it = backtrace_copy.begin(); it != end; it++) {
		delete *it;
	}
}

template<typename Collection>
static string
format_backtrace(const Collection &backtrace_list) {
	if (backtrace_list.empty()) {
		return "     (empty)";
	} else {
		backtrace_list.rbegin();
		stringstream result;
		typename Collection::const_reverse_iterator it;

		for (it = backtrace_list.rbegin(); it != backtrace_list.rend(); it++) {
			const trace_point *p = *it;

			result << "     in '" << p->function << "'";
			if (p->source != NULL) {
				const char *source = strrchr(p->source, '/');
				if (source != NULL) {
					source++;
				} else {
					source = p->source;
				}
				result << " (" << source << ":" << p->line << ")";
				if (p->m_hasDataFunc) {
					if (p->u.dataFunc.func != NULL) {
						char buf[64];

						memset(buf, 0, sizeof(buf));
						if (p->u.dataFunc.func(buf, sizeof(buf) - 1, p->u.dataFunc.userData)) {
							buf[63] = '\0';
							result << " -- " << buf;
						}
					}
				} else if (p->u.data != NULL) {
					result << " -- " << p->u.data;
				}
			}
			result << endl;
		}
		return result.str();
	}
}

string
tracable_exception::backtrace() const throw() {
	return format_backtrace< vector<trace_point *> >(backtrace_copy);
}

const char *
tracable_exception::what() const throw() {
	return "oxt::tracable_exception";
}

#endif /* OXT_BACKTRACE_IS_ENABLED */


void
initialize() {
	global_context = new global_context_t();
	init_thread_local_context_support();
	thread_local_context_ptr ctx = thread_local_context::make_shared_ptr();
	ctx->thread_number = 1;
	ctx->thread_name = "Main thread";
	set_thread_local_context(ctx);

	ctx->thread = pthread_self();
	global_context->registered_threads.push_back(ctx);
	ctx->iterator = global_context->registered_threads.end();
	ctx->iterator--;
}

void shutdown() {
	free_thread_local_context();
	delete global_context;
	global_context = NULL;
}


global_context_t::global_context_t()
	: next_thread_number(2)
{ }


thread_local_context_ptr
thread_local_context::make_shared_ptr() {
	// For some reason make_shared() crashes here when compiled with clang 3.2 on OS X.
	// Clang bug? We use 'new' to work around it.
	return thread_local_context_ptr(new thread_local_context());
}

thread_local_context::thread_local_context()
	: thread_number(0)
{
	thread = pthread_self();
	#ifdef __linux__
		tid = syscall(SYS_gettid);
	#endif
	syscall_interruption_lock.lock();
	#ifdef OXT_BACKTRACE_IS_ENABLED
		backtrace_list.reserve(50);
	#endif
}


string
thread::make_thread_name(const string &given_name) {
	if (given_name.empty()) {
		if (OXT_LIKELY(global_context != NULL)) {
			stringstream str;
			str << "Thread #";
			{
				boost::lock_guard<boost::mutex> l(global_context->thread_registration_mutex);
				str << global_context->next_thread_number;
			}
			return str.str();
		} else {
			return "(unknown)";
		}
	} else {
		return given_name;
	}
}

void
thread::thread_main(const boost::function<void ()> func, thread_local_context_ptr ctx) {
	set_thread_local_context(ctx);

	if (OXT_LIKELY(global_context != NULL)) {
		boost::lock_guard<boost::mutex> l(global_context->thread_registration_mutex);

		ctx->thread = pthread_self();
		global_context->next_thread_number++;
		global_context->registered_threads.push_back(ctx);
		ctx->iterator = global_context->registered_threads.end();
		ctx->iterator--;
		// Set this after setting 'iterator' to indicate
		// that push_back() has succeeded.
		ctx->thread_number = global_context->next_thread_number;
	}

	try {
		func();
	} catch (const thread_interrupted &) {
		// Do nothing.
	}
	// We don't care about other exceptions because they'll crash the process anyway.

	if (OXT_LIKELY(global_context != NULL)) {
		boost::lock_guard<boost::mutex> l(global_context->thread_registration_mutex);
		thread_local_context *ctx = get_thread_local_context();
		if (ctx != 0 && ctx->thread_number != 0) {
			global_context->registered_threads.erase(ctx->iterator);
			ctx->thread_number = 0;
		}
	}
	free_thread_local_context();
}

std::string
thread::name() const throw() {
	return context->thread_name;
}

std::string
thread::backtrace() const throw() {
	#ifdef OXT_BACKTRACE_IS_ENABLED
		spin_lock::scoped_lock l(context->backtrace_lock);
		return format_backtrace(context->backtrace_list);
	#else
		return "    (backtrace support disabled during compile time)";
	#endif
}

string
thread::all_backtraces() throw() {
	#ifdef OXT_BACKTRACE_IS_ENABLED
		if (OXT_LIKELY(global_context != NULL)) {
			boost::lock_guard<boost::mutex> l(global_context->thread_registration_mutex);
			list<thread_local_context_ptr>::const_iterator it;
			std::stringstream result;

			for (it = global_context->registered_threads.begin();
			     it != global_context->registered_threads.end();
			     it++)
			{
				thread_local_context_ptr ctx = *it;
				result << "Thread '" << ctx->thread_name <<
					"' (" << hex << showbase << ctx->thread << dec;
				#ifdef __linux__
					result << ", LWP " << ctx->tid;
				#endif
				result << "):" << endl;

				spin_lock::scoped_lock l(ctx->backtrace_lock);
				std::string bt = format_backtrace(ctx->backtrace_list);
				result << bt;
				if (bt.empty() || bt[bt.size() - 1] != '\n') {
					result << endl;
				}
				result << endl;
			}
			return result.str();
		} else {
			return "(OXT not initialized)";
		}
	#else
		return "(backtrace support disabled during compile time)";
	#endif
}

string
thread::current_backtrace() throw() {
	#ifdef OXT_BACKTRACE_IS_ENABLED
		thread_local_context *ctx = get_thread_local_context();
		if (OXT_LIKELY(ctx != NULL)) {
			spin_lock::scoped_lock l(ctx->backtrace_lock);
			return format_backtrace(ctx->backtrace_list);
		} else {
			return "(OXT not initialized)";
		}
	#else
		return "(backtrace support disabled during compile time)";
	#endif
}

void
thread::interrupt(bool interruptSyscalls) {
	int ret;

	boost::thread::interrupt();
	if (interruptSyscalls && context->syscall_interruption_lock.try_lock()) {
		do {
			ret = pthread_kill(native_handle(),
				INTERRUPTION_SIGNAL);
		} while (ret == EINTR);
		context->syscall_interruption_lock.unlock();
	}
}


} // namespace oxt

Youez - 2016 - github.com/yon3zu
LinuXploit