Re: close(2) while accept(2) is blocked

2013-04-04 Thread Andriy Gapon
on 30/03/2013 18:14 John-Mark Gurney said the following:
 As someone else pointed out in this thread, if a userland program
 depends upon this behavior, it has a race condition in it...
 
 Thread 1  Thread 2Thread 3
   enters routine to read
 enters routine to close
 calls close(3)
   open() returns 3
   does read(3) for orignal fd
 
 How can the original threaded program ensure that thread 2 doesn't
 create a new fd in between?  So even if you use a lock, this won't
 help, because as far as I know, there is no enter read and unlock
 mutex call yet...
 
 I decided long ago that this is only solvable by proper use of locking
 and ensuring that if you call close (the syscall), that you do not have
 any other thread that may use the fd.  It's the close routine's (not
 syscall) function to make sure it locks out other threads and all other
 are out of the code path that will use the fd before it calls close..
 
 If someone could describe how this new eject a person from read could
 be done in a race safe way, then I'd say go ahead w/ it...  Otherwise
 we're just moving the race around, and letting people think that they
 have solved the problem when they haven't...
 
 I think I remeber another thread about this from a year or two ago,
 but I couldn't find it...  If someone finds it, posting a link would
 be nice..
 

I wish to abstract as much as possible from how an application may use, misuse 
or
even abuse the close+ interaction.  But I think that the behavior that
provides more information / capabilities is preferable over the behavior that 
does
not.  E.g. your example above does not apply to a utility that has only two
threads.  The three threads problem can also be solved if all the threads
cooperate.  But as I've said.

-- 
Andriy Gapon
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: call suspend_cpus() under smp_ipi_mtx

2013-04-04 Thread Andriy Gapon
on 01/04/2013 17:52 John Baldwin said the following:
 Hmm, I think intr_table_lock used to be a spin lock at some point.  I don't 
 remember
 why we changed it to a regular mutex.  It may be that there was a lock order 
 reason
 for that. :(

I came up with the following patch:
http://people.freebsd.org/~avg/intr_table_lock.diff

Please note the witness change.  Part of it is to prepare for smp_ipi_mtx -
intr_table_lock order, but I also had to move entropy harvest mutex because it
is used with msleep_spin. Also intr_table_lock interacts with sched lock.

This seems to work without problems or any warnings with WITNESS 
!WITNESS_SKIPSPIN, but it is very possible that I am not exercising all the
relevant code paths.

P.S. Looking through history it seems that in r169391 intr_table_lock
was changed from a spinlock to a sx lock (later it was changed to the current
mutex).  The commit message explains why spinlock was not needed, but it doesn't
seem to say why it was unacceptable:

 Minor fixes and tweaks to the x86 interrupt code: - Split the intr_table_lock
into an sx lock used for most things, and a spin lock to protect intrcnt_index.
Originally I had this as a spin lock so interrupt code could use it to lookup
sources. However, we don't actually do that because it would add a lot of 
overhead
to interrupts, and if we ever do support removing interrupt sources, we can use
other means to safely do so w/o locking in the interrupt handling code. - 
Replace
is_enabled (boolean) with is_handlers (a count of handlers) to determine if a
source is enabled or not. This allows us to notice when a source is no longer in
use. When that happens, we now invoke a new PIC method (pic_disable_intr()) to
inform the PIC driver that the source is no longer in use. The I/O APIC driver
frees the APIC IDT vector when this happens. The MSI driver no longer needs to
have a hack to clear is_enabled during msi_alloc() and msix_alloc() as a result 
of
this change as well. - Add an apic_disable_vector() to reset an IDT vector back 
to
Xrsvd to complement apic_enable_vector() and use it in the I/O APIC and MSI code
when freeing an IDT vector. - Add a new nexus hook: nexus_add_irq() to ask the
nexus driver to add an IRQ to its irq_rman. The MSI code uses this when it 
creates
new interrupt sources to let the nexus know about newly valid IRQs. Previously 
the
msi_alloc() and msix_alloc() passed some extra stuff back to the nexus methods
which then added the IRQs. This approach is a bit cleaner. - Change the MSI sx
lock to a mutex. If we need to create new sources, drop the lock, create the
required number of sources, then get the lock and try the allocation again.


-- 
Andriy Gapon
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


Re: close(2) while accept(2) is blocked

2013-04-04 Thread Andriy Gapon
on 01/04/2013 18:22 John Baldwin said the following:
 I think you need to split the 'struct file' reference count into two different
 counts similar to the how we have vref/vrele vs vhold/vdrop for vnodes.  The
 fget for accept and probably most other system calls should probably be 
 equivalent
 to vhold, whereas things like open/dup (and storing an fd in a cmsg) should be
 more like vref.  close() should then be a vrele().

This model makes perfect sense.
Unfortunately, ENOTIME to work on this.

Meanwhile I am using the following patch specific to local domain sockets,
accept(2) and shutdown(2).  Turns out that the problematic application does both
shutdown(RDWR) and close(2), but that doesn't help on FreeBSD.
BTW, this is the application:
http://thread.gmane.org/gmane.os.freebsd.devel.office/1754
The patch does help.

Author: Andriy Gapon a...@icyb.net.ua
Date:   Thu Mar 28 20:08:13 2013 +0200

[test!] uipc_shutdown: use soisdisconnected instead of socantsendmore

So that in addition to disabling sends we also wake up threads blocked
in accept (on so_timeo in general).

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 9b60eab..e93d46c 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1074,7 +1074,7 @@ uipc_shutdown(struct socket *so)

UNP_LINK_WLOCK();
UNP_PCB_LOCK(unp);
-   socantsendmore(so);
+   soisdisconnected(so);
unp_shutdown(unp);
UNP_PCB_UNLOCK(unp);
UNP_LINK_WUNLOCK();


-- 
Andriy Gapon
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to freebsd-hackers-unsubscr...@freebsd.org


extend printf(9) %b format to allow 0 bits set

2013-04-04 Thread Sean Bruno
A small patch from my wanderings today for your review.  This patch to
kvprintf() allows me to set a %b format string of:

 \20\0unset\1ONESET\2TWOSET

In the case that the variable being compared has the value of 0, it will
display 0x0unset

http://people.freebsd.org/~sbruno/subr_prf.txt

Sean


signature.asc
Description: This is a digitally signed message part


Re: CFR: FireWire: Don't allow a tlabel to reference an xfer after free

2013-04-04 Thread Sean Bruno
On Thu, 2013-03-28 at 11:25 -0600, Will Andrews wrote:
 Diff: http://people.freebsd.org/~will/patches/fix-fwmem-use-after-free.diff
 
 From the commit log:
 
   FireWire: Don't allow a tlabel to reference an xfer after free.
   
   sys/dev/firewire/firewire.c:
   - fw_xfer_unload(): Since we are about to free this xfer, call
 fw_tl_free() to remove the xfer from its tlabel's list, if
 it has a tlabel.
   - In every occasion when a xfer is removed from a tlabel's list,
 reset xfer-tl to -1 while holding fc-tlabel_lock, so that the
 xfer isn't mis-identified as belonging to a tlabel.
 
 
 Thanks,
 --Will.
 ___

Ack.  Looks like a valid commit.

sean


signature.asc
Description: This is a digitally signed message part