_without_ using fork().
The problem with YPPROC_ALL is that it transmits an entire map through
a TCP pipe as the result of a single RPC call. First of all, this requires
certain hackery in the XDR filter. Second, if the map being sent is
large, the server can end up spending lots of time in the XDR filter
sending to just the one client, while requests for other clients will
go unanswered.
My original solution for this was to fork() the request into a child
process which terminates after the map has been transmitted (or the
transfer is interrupted due to an error). This leaves the parent free
to handle other requests. But this solution is kind of lame: fork()
is relatively expensive, and we have to keep a cap on the number of
child processes to keep from swamping the system.
What we do now is grab control of the service transport handle and XDR
handle from the RPC library and send the records one at a time ourselves
instead of letting the RPC library do it. We send a record, then go
back to the svc_run() loop and select() on the socket. If select() says
we can still write data, we send the next record. Then we call
svc_getreqset() and handle other RPCs and loop around again. This way,
we can handle other RPCs between records.
We manage multiple YPPROC_ALL requests using a circular queue. When a
request is done, we dequeue it and destroy the handle. We also tag
each request with a ttl which is decremented whevever we run the queue
and a handle isn't serviced. This lets us nuke requests that have sat
idle for too long (if we didn't do this, we might run out of socket
descriptors.)
Now all I have to do is come up with an async resolver, and ypserv
won't need to fork() at all. :)
Note: these changes should not go into 2.2 unless they get a very
throrough shakedown before the final cutoff date.
number of mail messages sent per run was lowered from 2 to 1. Why? Well,
some numbers just give you the warm fuzzies, like zero and one. Zero isn't
much use here, so I picked my all time favourite, one.
ttymsg() insists on them not being there.
Also, since ttymsg() opens the tty "on demand", don't keep an fd open
ourselves. This would interfere with HUPCL etc.
This should close PR#2103 from <xaa@stack.nl>
Fenner was kind enough to point out the error of my ways. This incorporates
diffs from him which:
- Keep everything in network order.
- Log the booted ether & ip address, instead of my address on that net
- change several exit()'s to return()'s, so that rarpd continues running
even if it thinks it's in a weird state.
One small tweak by me: in rarp_bootable(), we have to make sure to
construct 'ipname' in host byte order (if we don't, we have to
specify /tftpboot/<remote IP in hex> with <remote IP in hex> in
network byte order, which is confusing).
Also restored use of <dirent.h> rather than <sys/dir.h> as pointed
out by bde.
Also updated the man page so that the -v flag is documented.
With any luck, I won't have to touch this thing again.
- It no longer attempts to fiddle wall-vs-UTC-in-RTC. The results
were just confusing most of the time.
- The program no longer contains a pre-compiled list of timezones
(compiled by groveling through the tzdata source files for comments
starting with `ZONE-DESCR'). Now it uses the new `zone.tab' file
supplied with current versions of the timezone data files, to determine
the list at run time. (It also requires the ISO 3166 table I
committed some months ago.)
AS A RESULT, this program will NOT work until the new timezone data files
are committed (should happen sometime soon).
This includes the following changes:
- Support for poking ARP entries into the local table is now built
in, so the arptab.c module I hacked together is no longer needed.
- rarp_process() and rarp_reply() now accept a len argument which is
passed down from rarp_loop() which tells rarp_reply() exactly how
long the original RARP frame was. (Usually, it's 60 bytes, which is
the minimum.) Previously, the length was calculated using the sum
of sizeof(struct ether_header) + sizeof(struct ether_arp) (plus the
ethernet frame header, I think). The result was a total packet
length of 42 bytes. Now, rarp_reply() sends out packets that are
the same size as those it recieves (60 bytes). This agrees with the
behavior of rarpd on SunOS (as observed with tcpdump). The unused
extra bytes are zeroed.
the races in my previous commits here, and fix some other problems with
syslogd as well.
- if the child process exited early (eg: could not bind to the socket),
the boot process would hang for 30 seconds. The parent was not noticing
that the child had exited. (my fault)
- when writing to tty devices, instead of treating them like files that
need \r\n instead of \n, actually use ttymsg() which has specific code
intended to write to potentially blocking ttys safely. I had a machine
lock up last night because /dev/console on a serial port got flow control
blocked. Setting comcontrol drainwait fixed everything but syslogd which
was going into a spin trying to write to the console and completely
ignoreing everything else.
- fix a couple of nonsensical bits of code while here.. eg: wait3 takes
a pointer to an int. There is no sense in declaring it as 'union wait',
then casting the pointer to (int *), then forgetting about it.
Add printing of PCI header type register. (This makes the output
80 columns wide. Ughh. I'm looking for a better way to put the
information on one line ...)
and set the B and S variables here, but I forgot to actually add them to
the master.passwd and hosts.* targets. In other words, they weren't being
passed to yp_mkdb as needed.
This needs to go into 2.2; it doesn't break things a lot, but it leaves
your master.passwd maps available to unprivileged users without you
realizing it.