Ethereal-dev: Re: [ethereal-dev] Viewing packets while capturing...

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: guy@xxxxxxxxxx (Guy Harris)
Date: Wed, 6 Jan 1999 22:40:47 -0800 (PST)
> 4) pthread does use non-blocking kernel pipes (_thread_kern_pipe and
> _thread_sys_close.

"_thread_sys_close()" is, in "libc_r", the same as "close()", in "libc"
(at least in FreeBSD 2.2.7, but it's probably true elsewhere).

The same applies to all the *other* "_thread_sys_XXX()" routines; the
"libc_r" Makefile includes the "libc" "Makefile.inc", which probably
eventually drags in the "libc/sys" "Makefile.inc", which builds most
system call stubs by generating the assembler-language stub code on the
fly.  Note in that Makefile the stuff:

	# Syscalls renamed as _thread_sys_{syscall} when building libc_r.
	ASMR=   accept.o bind.o close.o connect.o dup.o dup2.o \
	        execve.o fchdir.o fchflags.o fchmod.o fchown.o fcntl.o \
	        flock.o fpathconf.o fstat.o fstatfs.o fsync.o getdirentries.o \
	        getpeername.o getsockname.o getsockopt.o ioctl.o listen.o \
	        mkfifo.o mknod.o nfssvc.o open.o read.o readv.o recvfrom.o \
	        recvmsg.o select.o sendmsg.o sendto.o setsockopt.o \
	        shutdown.o sigaction.o sigaltstack.o socket.o socketpair.o \
	        wait4.o write.o writev.o

which are the system calls around which "libc_r" adds wrappers.

"_thread_kern_pipe" is a pipe "that is written to by the signal handler
to prevent signals being missed in calls to _thread_sys_select" - if a
signal has been unblocked by "the pthread kernel", which is the userland
threading "kernel" that does thread context switches, etc., and a signal
arrives, it's "remembered" by writing the signal number to the pipe. 
The "_thread_sys_select()" done in the idle loop of that kernel may
select on that pipe, so that it returns immediately if a signal has been
posted to it.  It's non-blocking so that if a signal comes in during
that interval, and the "libc_r" signal handler wrapper tries to write to
it, the whole process doesn't block if the pipe is full (given that the
pthread kernel doesn't really care what's in the pipe, it only wants to
make sure it's non-empty when the "_thread_sys_select()" is done,
nothing is lost by a failed non-blocking write to the pipe).

All that stuff is part of a wrapper library of the sort I mentioned; the
wrapper library in question happens to be included as part of "libc_r",
rather than being a separate library.

It *looks* as if they Did The Right Thing with regards not only to
"read()" and "write()", but also "select()".

For example, "read()" and "write()" are wrappers around the underlying
system calls ("_thread_sys_read()" and "_thread_sys_write()"), with the
underlying file descriptors (the ones handed to the underlying system
calls) being in non-blocking mode *AND* with a separate non-blocking
state being kept in userland, so that a threaded program that uses
"read()" or "write()" on FDs that it hasn't put in what it thinks is
non-blocking mode or that it has put in what it thinks is blocking mode
gets traditional blocking behavior (that blocks the *thread*, not the
entire *process*), and a threaded program that uses them on descriptors
that it's put in what it thinks is non-blocking mode gets traditional
non-blocking behavior (but the descriptor is "really", from the
standpoint of the OS kernel - as opposed to the kernel to which the
"_kern_" in various names in stuff in the "uthread" directory refers,
which is the "pthread kernel".

Similarly, "select()" is a wrapper *and* the threading kernel (i.e., the
"pthread kernel") knows about file descriptors on which a select is
done.

The kernel (meaning "kernel-mode kernel", as opposed to "pthread
kernel") non-blocking mode used is O_NONBLOCK, so the question about
"/dev/bpf" is whether it supports that.  It appears that it supports the
FIONBIO "ioctl", and the old BSD hack of mapping "fcntl"s that change
O_NONBLOCK into FIONBIO "ioctl"s is still there, so it looks as if
"/dev/bpf" can be put in non-blocking mode.

This means that a threaded program that uses "select()" (such as an X
application) or that uses "/dev/bpf" (such as a packet capture program)
will *probably* work in recent FreeBSD when linked with "libc_r".

That probably also applies to {Net,Open}BSD.

I can't speak for other userland-thread-only UNIXes.  Hopefully, the
thread packages for them were done by people who remembered that there
could well be, for example, threaded programs that use "select()", and,
if they use non-blocking I/O to allow e.g. "read()" or "write()" to
block only a thread, have raw packet capture mechanisms that support the
non-blocking I/O mechanism in question.  One would hope they are, but
I'd try to check it out, first.