added moo_deregallfinalizables()
removed some unused code
This commit is contained in:
		@ -350,7 +350,7 @@ class MyObject(Object)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	method(#class) another_proc
 | 
						method(#class) another_proc: base_port
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		| httpd |
 | 
							| httpd |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -360,8 +360,8 @@ class MyObject(Object)
 | 
				
			|||||||
			[
 | 
								[
 | 
				
			||||||
				| ss |
 | 
									| ss |
 | 
				
			||||||
				httpd start: %(
 | 
									httpd start: %(
 | 
				
			||||||
					SocketAddress fromString: '[::]:8666',
 | 
										SocketAddress fromString: ('[::]:' & base_port asString),
 | 
				
			||||||
					SocketAddress fromString: '0.0.0.0:8665'
 | 
										SocketAddress fromString: ('0.0.0.0:' & (base_port + 1) asString)
 | 
				
			||||||
				).
 | 
									).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				while (true) 
 | 
									while (true) 
 | 
				
			||||||
@ -382,8 +382,9 @@ class MyObject(Object)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		| httpd |
 | 
							| httpd |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[ self another_proc ] fork.
 | 
							[ self another_proc: 5000 ] fork.
 | 
				
			||||||
		###[ self another_proc ] fork.
 | 
							[ self another_proc: 5100 ] fork.
 | 
				
			||||||
 | 
							[ self another_proc: 5200 ] fork.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[
 | 
							[
 | 
				
			||||||
			thisProcess initAsync.
 | 
								thisProcess initAsync.
 | 
				
			||||||
@ -406,6 +407,7 @@ class MyObject(Object)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		] on: Exception do: [:ex | ('Exception - '  & ex messageText) dump].
 | 
							] on: Exception do: [:ex | ('Exception - '  & ex messageText) dump].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		'----- END OF MAIN ------' dump.
 | 
							'----- END OF MAIN ------' dump.
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -225,20 +225,12 @@ class(#byte) SocketAddress(Object) from 'sck.addr'
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SocketCore(Object) from 'sck'
 | 
				
			||||||
class Socket(Object) from 'sck'
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	## the handle must be the first field in this object to match
 | 
						## the handle must be the first field in this object to match
 | 
				
			||||||
	## the internal representation used by various modules. (e.g. sck)
 | 
						## the internal representation used by various modules. (e.g. sck)
 | 
				
			||||||
	var(#get) handle := -1.
 | 
						var(#get) handle := -1.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var(#get) closedEventAction.
 | 
					 | 
				
			||||||
	var(#get) dataInEventAction.
 | 
					 | 
				
			||||||
	var(#get) dataOutEventAction.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var pending_bytes, pending_offset, pending_length.
 | 
					 | 
				
			||||||
	var outreadysem, outdonesem, inreadysem.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	method(#primitive) open(family, type, proto).
 | 
						method(#primitive) open(family, type, proto).
 | 
				
			||||||
	## map the open primitive again with a different name for strict internal use only.
 | 
						## map the open primitive again with a different name for strict internal use only.
 | 
				
			||||||
	## this method is supposed to be used to handle an accepted socket in server sockets.
 | 
						## this method is supposed to be used to handle an accepted socket in server sockets.
 | 
				
			||||||
@ -257,6 +249,12 @@ class Socket(Object) from 'sck'
 | 
				
			|||||||
	method(#primitive) _writeBytes: bytes offset: offset length: length.
 | 
						method(#primitive) _writeBytes: bytes offset: offset length: length.
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Socket(SocketCore)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						var pending_bytes, pending_offset, pending_length.
 | 
				
			||||||
 | 
						var outreadysem, outdonesem, inreadysem.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(* TODO: generate these family and type from the C header *)
 | 
					(* TODO: generate these family and type from the C header *)
 | 
				
			||||||
pooldic Socket.Family
 | 
					pooldic Socket.Family
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -277,17 +275,20 @@ extend Socket
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	method(#class) __with: handle
 | 
						method(#class) __with: handle
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							###self addToBeFinalized.
 | 
				
			||||||
		^(self _basicNew initialize) __open(handle)
 | 
							^(self _basicNew initialize) __open(handle)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	method(#class) family: family type: type
 | 
						method(#class) family: family type: type
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							###self addToBeFinalized.
 | 
				
			||||||
		## new is prohibited. so use _basicNew with initialize.
 | 
							## new is prohibited. so use _basicNew with initialize.
 | 
				
			||||||
		##^(self new) open(family, type, 0)
 | 
							##^(self new) open(family, type, 0)
 | 
				
			||||||
		^(self _basicNew initialize) open(family, type, 0)
 | 
							^(self _basicNew initialize) open(family, type, 0)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	(* -------------------
 | 
						(* -------------------
 | 
				
			||||||
 | 
						socket call-back methods
 | 
				
			||||||
	  socketClosing
 | 
						  socketClosing
 | 
				
			||||||
	  socketClosed
 | 
						  socketClosed
 | 
				
			||||||
	  socketDataIn
 | 
						  socketDataIn
 | 
				
			||||||
@ -305,10 +306,6 @@ socketConnected:
 | 
				
			|||||||
		self.inreadysem := Semaphore new.
 | 
							self.inreadysem := Semaphore new.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		self.outdonesem signalAction: [ :sem |
 | 
							self.outdonesem signalAction: [ :sem |
 | 
				
			||||||
			##if (self.dataOutEventAction notNil)
 | 
					 | 
				
			||||||
			##{
 | 
					 | 
				
			||||||
			##	self.dataOutEventAction value: self.
 | 
					 | 
				
			||||||
			##}.
 | 
					 | 
				
			||||||
			self onSocketDataOut.
 | 
								self onSocketDataOut.
 | 
				
			||||||
			System unsignal: self.outreadysem.
 | 
								System unsignal: self.outreadysem.
 | 
				
			||||||
		].
 | 
							].
 | 
				
			||||||
@ -337,16 +334,18 @@ socketConnected:
 | 
				
			|||||||
		].
 | 
							].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		self.inreadysem signalAction: [ :sem |
 | 
							self.inreadysem signalAction: [ :sem |
 | 
				
			||||||
			###self.dataInEventAction value: self.
 | 
					 | 
				
			||||||
			self onSocketDataIn.
 | 
								self onSocketDataIn.
 | 
				
			||||||
		].
 | 
							].
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(*
 | 
				
			||||||
	method finalize
 | 
						method finalize
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
'SOCKET FINALIZED...............' dump.
 | 
					'SOCKET FINALIZED...............' dump.
 | 
				
			||||||
		self close.
 | 
							self close.
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					*)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	method close
 | 
						method close
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -375,35 +374,10 @@ socketConnected:
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			self _close.
 | 
								self _close.
 | 
				
			||||||
			self.handle := -1.
 | 
								self.handle := -1.
 | 
				
			||||||
 | 
					 | 
				
			||||||
			##if (self.closedEventAction notNil) 
 | 
					 | 
				
			||||||
			##{
 | 
					 | 
				
			||||||
			##	self.closedEventAction value: self.
 | 
					 | 
				
			||||||
			##}.
 | 
					 | 
				
			||||||
			self onSocketClosed.
 | 
								self onSocketClosed.
 | 
				
			||||||
		}.
 | 
							}.
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	method onEvent: event_type do: action_block
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (event_type == #closed)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			self.closedEventAction := action_block.
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		elsif (event_type == #data_in) 
 | 
					 | 
				
			||||||
		{ 
 | 
					 | 
				
			||||||
			self.dataInEventAction := action_block.
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		elsif (event_type == #data_out)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			self.dataOutEventAction := action_block.
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Exception signal: 'unknown event type ' & event_type asString.
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	method beWatched
 | 
						method beWatched
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		thisProcess addAsyncSemaphore: self.inreadysem.
 | 
							thisProcess addAsyncSemaphore: self.inreadysem.
 | 
				
			||||||
@ -488,7 +462,6 @@ class ClientSocket(Socket)
 | 
				
			|||||||
				System unsignal: sem.
 | 
									System unsignal: sem.
 | 
				
			||||||
				thisProcess removeAsyncSemaphore: sem.
 | 
									thisProcess removeAsyncSemaphore: sem.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				##self.connectedEventAction value: self value: (soerr == 0).
 | 
					 | 
				
			||||||
				self onSocketConnected: (soerr == 0).
 | 
									self onSocketConnected: (soerr == 0).
 | 
				
			||||||
				if (soerr == 0) { self beWatched }.
 | 
									if (soerr == 0) { self beWatched }.
 | 
				
			||||||
			}.
 | 
								}.
 | 
				
			||||||
@ -507,16 +480,6 @@ class ClientSocket(Socket)
 | 
				
			|||||||
		^super close
 | 
							^super close
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	method onEvent: event_type do: action_block
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (event_type == #connected)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			self.connectedEventAction := action_block.
 | 
					 | 
				
			||||||
			^self.
 | 
					 | 
				
			||||||
		}.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		^super onEvent: event_type do: action_block
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	method connect: target
 | 
						method connect: target
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		| sem |
 | 
							| sem |
 | 
				
			||||||
@ -529,7 +492,6 @@ class ClientSocket(Socket)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			## connected immediately
 | 
								## connected immediately
 | 
				
			||||||
'IMMEDIATELY CONNECTED.....' dump.
 | 
					'IMMEDIATELY CONNECTED.....' dump.
 | 
				
			||||||
			###self.connectedEventAction value: self value: true.
 | 
					 | 
				
			||||||
			self onSocketConnected: true.
 | 
								self onSocketConnected: true.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			thisProcess addAsyncSemaphore: self.inreadysem.
 | 
								thisProcess addAsyncSemaphore: self.inreadysem.
 | 
				
			||||||
@ -540,6 +502,7 @@ class ClientSocket(Socket)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	method onSocketConnected
 | 
						method onSocketConnected
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 | 
							## do nothing special. the subclass may override this method.
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -556,7 +519,6 @@ class ServerSocket(Socket)
 | 
				
			|||||||
			| cliaddr clisck cliact fd |
 | 
								| cliaddr clisck cliact fd |
 | 
				
			||||||
			cliaddr := SocketAddress new.
 | 
								cliaddr := SocketAddress new.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
'IN READYSEM action performing.........' dump.
 | 
					 | 
				
			||||||
			fd := self _accept: cliaddr.
 | 
								fd := self _accept: cliaddr.
 | 
				
			||||||
			##if (fd >= 0)
 | 
								##if (fd >= 0)
 | 
				
			||||||
			if (fd notNil)
 | 
								if (fd notNil)
 | 
				
			||||||
@ -581,17 +543,6 @@ class ServerSocket(Socket)
 | 
				
			|||||||
		^super close.
 | 
							^super close.
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	method onEvent: event_type do: action_block
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (event_type == #accepted)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			self.acceptedEventAction := action_block.
 | 
					 | 
				
			||||||
			^self.
 | 
					 | 
				
			||||||
		}.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		^super onEvent: event_type do: action_block
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	method listen: backlog
 | 
						method listen: backlog
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		| n |
 | 
							| n |
 | 
				
			||||||
@ -600,9 +551,10 @@ class ServerSocket(Socket)
 | 
				
			|||||||
		## added to the multiplexer, a spurious hangup event might
 | 
							## added to the multiplexer, a spurious hangup event might
 | 
				
			||||||
		## be generated. At least, such behavior was observed
 | 
							## be generated. At least, such behavior was observed
 | 
				
			||||||
		## in linux with epoll in the level trigger mode.
 | 
							## in linux with epoll in the level trigger mode.
 | 
				
			||||||
		###  System signal: self.inreadysem onInput: self.handle.
 | 
							##    System signal: self.inreadysem onInput: self.handle.
 | 
				
			||||||
		###  thisProcess addAsyncSemaphore: self.inreadysem.
 | 
							##    thisProcess addAsyncSemaphore: self.inreadysem.
 | 
				
			||||||
		###  n := self _listen: backlog.
 | 
							##    self _listen: backlog.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		n := self _listen: backlog.
 | 
							n := self _listen: backlog.
 | 
				
			||||||
		System signal: self.inreadysem onInput: self.handle.
 | 
							System signal: self.inreadysem onInput: self.handle.
 | 
				
			||||||
		thisProcess addAsyncSemaphore: self.inreadysem.
 | 
							thisProcess addAsyncSemaphore: self.inreadysem.
 | 
				
			||||||
 | 
				
			|||||||
@ -193,6 +193,11 @@ static MOO_INLINE void vm_cleanup (moo_t* moo)
 | 
				
			|||||||
	moo->sem_gcfin = (moo_oop_semaphore_t)moo->_nil;
 | 
						moo->sem_gcfin = (moo_oop_semaphore_t)moo->_nil;
 | 
				
			||||||
	moo->sem_gcfin_sigreq = 0;
 | 
						moo->sem_gcfin_sigreq = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* deregister all pending finalizable objects pending just in case these
 | 
				
			||||||
 | 
						 * have not been removed for various reasons. (e.g. sudden VM abortion)
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						moo_deregallfinalizables (moo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MOO_DEBUG0 (moo, "VM cleaned up\n");
 | 
						MOO_DEBUG0 (moo, "VM cleaned up\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								moo/lib/gc.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								moo/lib/gc.c
									
									
									
									
									
								
							@ -1088,14 +1088,34 @@ int moo_deregfinalizable (moo_t* moo, moo_oop_t oop)
 | 
				
			|||||||
		{
 | 
							{
 | 
				
			||||||
			MOO_OBJ_SET_FLAGS_GCFIN(oop, (MOO_OBJ_GET_FLAGS_GCFIN(oop) & ~MOO_GCFIN_FINALIZABLE));
 | 
								MOO_OBJ_SET_FLAGS_GCFIN(oop, (MOO_OBJ_GET_FLAGS_GCFIN(oop) & ~MOO_GCFIN_FINALIZABLE));
 | 
				
			||||||
			MOO_DELETE_FROM_LIST (&moo->finalizable, x);
 | 
								MOO_DELETE_FROM_LIST (&moo->finalizable, x);
 | 
				
			||||||
 | 
								moo_freemem (moo, x);
 | 
				
			||||||
			return  0;
 | 
								return  0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							x = x->next;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	moo_seterrnum (moo, MOO_ENOENT);
 | 
						moo_seterrnum (moo, MOO_ENOENT);
 | 
				
			||||||
	return -1;
 | 
						return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void moo_deregallfinalizables (moo_t* moo)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						moo_finalizable_t* x, * nx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x = moo->finalizable.first;
 | 
				
			||||||
 | 
						while (x)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							nx = x->next;
 | 
				
			||||||
 | 
							MOO_OBJ_SET_FLAGS_GCFIN(x->oop, (MOO_OBJ_GET_FLAGS_GCFIN(x->oop) & ~MOO_GCFIN_FINALIZABLE));
 | 
				
			||||||
 | 
							MOO_DELETE_FROM_LIST (&moo->finalizable, x);
 | 
				
			||||||
 | 
							moo_freemem (moo, x);
 | 
				
			||||||
 | 
							x = nx;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MOO_ASSERT (moo, moo->finalizable.first == MOO_NULL);
 | 
				
			||||||
 | 
						MOO_ASSERT (moo, moo->finalizable.last == MOO_NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static moo_oow_t move_finalizable_objects (moo_t* moo)
 | 
					static moo_oow_t move_finalizable_objects (moo_t* moo)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	moo_finalizable_t* x, * y;
 | 
						moo_finalizable_t* x, * y;
 | 
				
			||||||
 | 
				
			|||||||
@ -1194,6 +1194,7 @@ moo_oop_nsdic_t moo_makensdic (
 | 
				
			|||||||
/* ========================================================================= */
 | 
					/* ========================================================================= */
 | 
				
			||||||
int moo_regfinalizable (moo_t* moo, moo_oop_t oop);
 | 
					int moo_regfinalizable (moo_t* moo, moo_oop_t oop);
 | 
				
			||||||
int moo_deregfinalizable (moo_t* moo, moo_oop_t oop);
 | 
					int moo_deregfinalizable (moo_t* moo, moo_oop_t oop);
 | 
				
			||||||
 | 
					void moo_deregallfinalizables (moo_t* moo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ========================================================================= */
 | 
					/* ========================================================================= */
 | 
				
			||||||
/* proc.c                                                                    */
 | 
					/* proc.c                                                                    */
 | 
				
			||||||
 | 
				
			|||||||
@ -631,6 +631,7 @@ static void gc_mod_sck (moo_t* moo, moo_mod_t* mod)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int moo_mod_sck (moo_t* moo, moo_mod_t* mod)
 | 
					int moo_mod_sck (moo_t* moo, moo_mod_t* mod)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
	if (mod->hints & MOO_MOD_LOAD_FOR_IMPORT)
 | 
						if (mod->hints & MOO_MOD_LOAD_FOR_IMPORT)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		mod->gc = MOO_NULL;
 | 
							mod->gc = MOO_NULL;
 | 
				
			||||||
@ -656,6 +657,7 @@ int moo_mod_sck (moo_t* moo, moo_mod_t* mod)
 | 
				
			|||||||
		mod->gc = gc_mod_sck;
 | 
							mod->gc = gc_mod_sck;
 | 
				
			||||||
		mod->ctx = ctx;
 | 
							mod->ctx = ctx;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mod->import = import;
 | 
						mod->import = import;
 | 
				
			||||||
	mod->query = query;
 | 
						mod->query = query;
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user