summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES457
-rw-r--r--emu/port/devsrv.c198
-rw-r--r--man/3/srv2
-rw-r--r--os/port/devsrv.c204
4 files changed, 300 insertions, 561 deletions
diff --git a/CHANGES b/CHANGES
index d8e228ed..c0499e04 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+20101220
+ changes to srv(3) to notify client when server vanishes [issue 244, thanks to powerman and roger]
20101205
change a few types in ipif-posix.c to appease the gods
emu/MacOSX/mkfile - include portmkfile at correct point for LIBFILES to work (and other, minor, changes) [issue 24]
@@ -360,457 +362,4 @@
20071015
add cap creation to infauth in server role in factotum
20071011
- remove obsolete references to sh-exception(2)
-20071010
- add abhey's changes for cmd key as unicode compose key for MacOS X to emu/MacOSX/win.c
-20071008
- nemo's change to emu/port/random.c; really the file needs a little rewriting for clarity (too many overlapping states)
-20071002
- ensure fmtdef.h included by some lib9 functions so that va_copy is defined on older systems that lack that needless notion
- <{} and >{} added to sh(1)
-20070929
- move emu/MacOSX/mkfile to .../mkfile-x11 and replace it by the variant that builds for Carbon, now the default
-20070927
- add working drawcursor to emu/MacOSX/win.c, based on mirtchovski's changes (but mapping general cursor images to Mac's form)
-20070910
- update spki(2) [change handling of hashes, add signature functions] appl/lib/spki/spki.b module/spki.m, updated for GSoC
-20070906
- add toreal to string(2)
-20070905
- /appl/cmd/ed.b (caerwyn's fix for g/.../d)
- also /appl/lib/ecmascript/builtin.b (toupper fix)
-20070902
- make /appl/lib/daytime.b accept Daytime->text's output; add string2tm to man page (issue 59)
-20070901
- add andrey's changes to emu/MacOSX/win.c (used by emu/MacOSX/mkfile-a)
- add saoret's changes to dis/lookman, dis/man (issue 58)
- add micah.stetson's change to /appl/cmd/src.b (issue 57)
-20070817
- two old changes that weren't in the distribution...
- libkeyring/rsaalg.c: previously failed to ensure the output key was the right length (really rsagen should do that)
- libinterp/alt.c: use a better random number generator
-20070814
- bufio.b didn't update the buffer pointers correctly on write errors
-20070807
- libinterp/keyring.c don't include owner= if owner is nil or ""
- add auth/rsagen
-20070806
- /module/lists.m add PATH(!), also simplify concat implementation
-20070725
- /dis/man initialise fils correctly to empty list and remove hack (issue 56)
-20070720
- utils/5l/asm.c: ensure SBZ field in MOV is regarded as MBZ (ie, force to zero)
-20070714
- add Sys->readn, update sys-read(2)
- copy two repairs from emu/port/inferno.c to os/port/inferno.c
- remove readn implementation from several commands
- print correct diagnostic in appl/cmd/crypt.b
- prevent window titlebars from being dragged out of the main window in wm/wm.b
-20070619
- remembered to include /appl/cmd/trfs.b /dis/trfs.dis
-20070614
- /appl/lib/venti.b bug fixes, a few more errstrs, remove prints to stderr
- add initial module/vac.m appl/lib/vac.b from mjl (gsoc project ventivac)
- add initial /appl/cmd/^(vacfs.b vacget.b vacput.b) /man/4/vacfs /man/1/vacget from mjl (gsoc:ventivac)
- include omitted man/mkfile man/lib
-20070608
- update /lib9 functions to use silly va_copy (and then va_end) instead of just assigning, to account for silly C implementations
- change /appl/cmd/mc.b not to require Draw or Env (so lc works on smaller systems)
- update acme to include the font size data (eg, for use by mc(1))
-20070607
- /appl/wm/man.b /appl/lib/man.b to allow 10.1 etc as section references
-20070605
- add another xopen #define to lib9.h includes for Linux
- copy plan9 acme's colormix
-20070601
- /appl/cmd/ls.b /dis/ls.dis /man/1/ls: document new -F option and -T option
- /appl/cmd/auth/factotum/factotum.b: ignore empty writes, don't fail; make a few diagnostics match plan 9
- rename /appl/cmd/mc.b to /appl/cmd/calc.b; also /man/1/mc to /man/1/calc; /dis/mc.dis to /dis/calc.dis
- add /appl/cmd/mc.b (initial version)
- replace /dis/lc.dis by /dis/lc; remove /appl/cmd/lc.b
- remove /appl/cmd/mathcalc.b /dis/mathcalc.dis /man/1/mathcalc
-20070510
- quickly remove references to udp's "oldheaders" because plan 9 removed it
- remove obootpd completely
-20070418
- add scan code to X11 (issue 45)
-20070411
- if mkconfig has been changed from the distribution, use it to set parameters in makemk.sh (issue 41)
- add iso8859-15 (what? will the line stretch on to the crack of doom?) (issue 43)
-20070410
- fix some porting errors in /appl/cmd/look.b
- document look's -r option in look(1)
-20070407
- /os/port/^(portdat.h lib.h portfns.h xalloc.c) compatiblity changes with plan 9
- /os/pc ether drivers updated to match plan 9, and os/ip (and a few files in /os/port) also updated, including removing some unreachable code
- /os/ip/tcp.c changes from plan 9 for out-of-sequence segments
-20070319
- emu/port/devsrv.c and os/port/devsrv.c delete wc at correct time
-20070312
- rename -D and -k options to plumb (old ones still accepted); add -i option to take data from standard input; update man page
- enable 64-bit seeks in /emu/Nt/devfs.c
-20070302
- change /mkfile to build yacc earlier, mainly to make bootstrap of a new host easier (makemk.sh and mk install)
- change /utils/mkfile not to build k[acl] and q[acl] on Plan 9, since the system ones are the same
-20070228
- make array bounds checking the default for on-the-fly compilers (emu/port/main.c)
- improve wording in security-ssl(2) and ssl(3)
-20070227
- /include/fcall.h: ensure unsigned promotion to counter ansi sign-extending rules for GBIT64
- /libmemdraw/draw.c: copy fix to memfillcolor
-20070220
- add 0x92 as chip ID for ether91c111.c
-20070217
- repair /appl/lib/libc.b and /appl/lib/libc0.b strncmp implementations (used only by c2l output) [inferno-os issue 9]
- /emu/port/devip.c, get socket fd on reopen of ctl
- /appl/acme/exec.b, trim string correctly [inferno-os issue 11]
-20070216
- add /module/lists.m, /appl/lib/lists.b, and lists(2)
-20070209
- remove debugging -d option to exportfs call in emu/Plan9/devsrv9.c(!)
-20070206
- /appl/svc/auth.sh: replace exit by raise
- /man/2/styxservers: document replychan and replydirect
-20070201
- update US timezone files to save energy
-20070131
- add /appl/lib/convcs/utf16_btos.b, utf16_stob.b etc [rog]
-20070130
- fix wording in some of the licence files (eg, remove references to old liberal licence)
-20070123
- check lengths properly in devenv.c
- move all of doc into lib/proto/inferno from lib/proto/src
-20070122
- add doc/port.ms, doc/port.pdf to src proto. add brief instructions for source rebuild to port.ms
-20070118
- add json(2) {/appl/lib/json.b, /module/json.m, /dis/lib/json.dis} for RFC4627 notation [json(6)]
-20070117
- remove duplicate libmp/libsec reference from /mkfile (i assume it wasn't necessary to visit them twice!)
-20070116
- move Man from /dis/man.dis (which vanished a few changes ago) to /dis/lib/man.dis. honestly. wm/man works again.
-20070114
- remove some unused static declarations in /utils/mk/shprint.c
-20070111
- delete drawxflush from devdraw.c (call drawq(un)?lock instead)
-20070107
- have emu (/emu/port/main.c) check environment variables INFERNO and ROOT before EMU and -r, for inferno root directory
- (haven't yet changed the build system and mkfiles to match)
- remove /include/libcrypt_o.h since the library isn't used
- add complete(2)
-20070103
- replace man.dis by Salva Peiró's sh version of plan 9's man script
-20061221
- add data2c to Irix package prototype
- remove unwanted .dis/.sbl files from /appl packages
- change liblogfs to GPLv2 from proprietary, to fit google code
- correct cmd(3) to account for new stderr file
-20061219
- cmd(3) and thus os(1) change to separate standard output and error streams
- all /emu/*/cmd.c change to account for that (original changes to devcmd.c and MacOSX/cmd.c courtesy Cibernet)
-20061215
- replaced things like <???> because gcc annoyingly whines even with 1950's trigraphs off
- libtk/textu.c: uninitialised field in boundary case
- libtk/textw.c: possibly uninitialised value; leave unchanged
- utils/ql/l.h: uchar as to ushort, because of extra ops
-20061214
- added fopen to xml.m to allow bufio->sopen and others to be used
-20061213
- added MacOSX/386 components
-20061013
- updated /os/ip/lookbackmedium.c and /os/ip/rudp.c
-20061021
- change /os/port/exportfs.c to allow negotiating up to 64k msize
- (matching /emu/port/exportfs.c)
-20060809
- /appl/lib/newns.b uses String->unquoted, if it can load it
-20060803
- /libtk/textw.c: default page up/down scrolls 0.75 of a page (to give context); also allows fractional value
-20060801
- /utils/data2s/data2s.c: allocate at least one linker byte to empty files to avoid complaints
-20060715
- /appl/lib/pop3.b remove defaultserver(); update pop3(2) to remove references to /services
- similarly update smtp(2)
- avoid some boundary cases in /appl/charon/^(build.b layout.b)
-20060625
- added caerwynj@gmail.com changes to /appl/acme/acme/mail/src/Mailpop3.b
-20060622
- /appl/lib/sets*.b: correct op's implementation of 2r1101
-20060613
- added csv(2), /module/csv.m, /appl/lib/csv.b
-20060608
- preliminary rfc822(2), /appl/lib/rfc822.b
-20060605
- /appl/lib/chanfill.b: remove alt => *
-20060601
- fix /appl/lib/dis.b to save the real array once read in
-20060526
- /appl/lib/venti.b: fix g64's byte ordering [not that it is, or can be called yet]
-20060524
- copy end fix to lib*/utfecpy.c
-20060523
- w3c-uris(2): add a .copy() operation
-20060518
- /Nt/386/include/lib9.h define _USE_32BIT_TIME_T and deprecate `deprecated' warnings
-20060504
- remove use of HEAP_ALIGN from /*/port/devprof.c; change Heap.pad to Heap.hprof in /include/interp.h
-20060426
- correct text and selection colours in wm/sh for loss-of-focus and holding modes
-20060423
- add /appl/lib/w3c/uris.b w3c-uris(2) /module/uris.m
-20060419
- /emu/port/devcmd.c: correct wakeup state for started command
-20060412
- /appl/svc/webget include caerwyn's changes
-20060411
- put `|| exit 1' after each (command-list) in the mkfiles, just for bash
-20060410
- /appl/cmd/limbo/typecheck.b /limbo/typecheck.c - stop wrong warning wrt use of ref fn
-20060313
- remembered to install cddb port from last year... cddb(7)
-20060312
- /emu/Nt/win.c; #define windows names out of the way to remove IPoint etc
- /emu/Nt/os.c, simplify osblock/osready and eliminate erendezvous
- /emu/port/devcons.c, tug into line with /os/port, to prepare for single-window changes
- echo ^U on CAN (ctrl-U)
-20060311
- replace Limbo version of shutdown by sh script; it's still a bit silly
-20060309
- /*/port/inferno.c: 0 or -1 return value from dial functions
- /os/port/portmkfile: remove reference to ../kfs
- /man/8/httpd document -a; /appl/svc/httpd/httpd.b
- /libmp/port/mptouv.c sign extension fix from 9
- /module/keyring.m, /libinterp/ipint.c: add some bitwise operators
- change (undocumented) /appl/cmd/test.b so that `host' mkfiles will work in Inferno
- should probably change the mkfiles to replace it
-20060303
- /emu/Plan9/win.c replace ldepthof
-20060302
- add KPX11 flag to hosted kproc to boost the stack for silly x11 & co.
- put keyboard and cursor processing into a separate kproc with big stack in /emu/port/win-x11a.c
- change various os.c to match
-20060301
- /appl/cmd/rioimport.b fix initialisation race
-20060227
- fix /utils/ql/l.h: oprange should be [ALAST] (with extra 405xx opcodes), also AEND->ALIST elsewhere
- put faster gethunk in ql and kl (mimic other compilers)
-20060226
- enable /emu/port/devpointer.c, with changes to /emu/*/win*.c to call mousetrack, /emu/port/main.c to bind #m,
- and code for pointer and cursor removed from devcons.c
- update Nt/win.c and port/win-x11a.c from drawterm to get/put host snarf buffer
- change devmem.c from #m to #% not to clash with pointer
-20060225
- add /emu/port/devsnarf.c (#^) and put clipread from drawterm in /emu/Nt/win.c
-20060224
- modify /appl/lib/secstore.b, /module/secstore.m, secstore(2) [add dial, auth, mkseckey, mkfilekey, remove]
- add /appl/cmd/auth/secstore.b, secstore(1)
- remove strange exception handling in /appl/cmd/dd.b
- add dhcpclient(2)
-20060223
- add /appl/cmd/auth/aescbc.c
- add /appl/cmd/crypt.b [rog]
- add crypt(1)
- add /appl/lib/secstore.b /module/secstore.m secstore(2)
-20060221
- /libsec/port/hmac.c: treat existing but not seeded digest correctly
- /libinterp/ipint.c, /module/keyring.m, add new operator `invert'
-20060220
- add ida(2), /appl/lib/ida, /module/ida.m
-20060216
- add ubfa(2), ubfa(6), /module/ubfa.m, /appl/lib/ubfa.b
-20060214
- [rog] add cursor changing support to tk, wm, wmlib (eg, for acme)
-20060213
- remove libcrypt_o from distribution
-20060211
- add /man/1/9win [rog]
- change /appl/cmd/auth/keyfs.b to confirm key only when creating the file [rog]
- punt floating-point conversions in powerpc jit on macos for time being
- (have particular values in certain FP registers when native)
-20060210
- update /libmemdraw/draw.c to include 9's changes for concurrent use
- remove canlock as assembly language interface, replaced by _tas
- replace native use of tas by _tas; make declarations all agree
- add holdon/holdoff ctl request to wm/sh
- wmproxy in appl/lib/wmlib.b does not create new pgrp
-20060206
- update /appl/cmd/cp.b with digbyt's changes (mode/uid/gid correct on copied directories)
-20060203
- update /appl/cmd/ip/dhcp.b /appl/cmd/lib/dhcpclient.b
- update /os/init/i4e.b to use it
- add /man/8/dhcp
-20060118
- add ksize(10.1), kstrip(10.1), /utils/kstrip
- new _MAGIC definitions in utils/libmach/a.out.h
-20060114
- change /os/boot/arm1110 mkfile to work on unix and windows; add to /lib/proto/os
-20060111
- -s (exportonly) -x/-y (geometry) options to 9win (TODO: rog, manual page!)
- wm/sh.b: correct hold mode; remove little-used and undocumented history file
-20060109
- delete #pragma from flate.h
- ensure lib9 compiles replacement sbrk for MacOSX
-20060106
- update compilers
- update compilers' manual page
- fix os/port/portmkfile for Plan 9: don't use $OBJDIR but Inferno/$OBJTYPE
- have os/port/portmkfile check for i$CONF.p9 and use that not i$CONF for acid
- add srclist(10.1)
-20060105
- account for new definition of rendezvous (void* not ulong)
- add dummy setmalloctag to utils where needed (for Plan 9)
- set profileflg only for ATEXT in utils/?c/txt.c
- update /os/boot/pc
-20060103
- /os/ip updated from Plan 9
- /os/ip/^(bootp.c dhcp.c ihbootp.c) changed to use announce not connect for udp
-20051215
- /man/6/keytext added
-20051207
- /tools/odbc.c portability changes, and fix modes on several files
-20051202
- /emu/Plan9/devfs.c strip Inferno root from file system diagnostics
-20051130
- change /appl/svc/httpd to use lock(2) not lockprocs
-20051123
- /appl/cmd/bind.b changed not to use arg.dis, implement -q, and diagnostic change
- /appl/cmd/mount.b acquired a -q option as well
-20051114
- avoid limit==0 in wm/memory.b
-20051108
- have poolmaxsize return 0 for pool of size 0
- remove /os/*/u.h (in favour of /$SYSTARG/$OBJTYPE/include/u.h)
- update mkfiles accordingly
- adjust mkfiles for libsec and libmp compilation for native kernels
-20051107
- added /os/manga
-20051101
- fixed /os/port/devloopback.c
- updated netif.c netif.h
-20051028
- updated gettar(1) and /appl/cmd/gettar.b
-20051025
- fix British Summer Time in locales
-20051021
- updated /appl/lib/newns.b and namespace(6) for environment variable substitution
-20051018
- moved in changes from home to os/port: cis.c devbridge.c ethermii.c portclock.c devuart.c devbench.c random.c portfns.h tod.c uart.h
- - mainly for changes to implement fasttick and timers
-20051017
- /limbo/ecom.c and /appl/cmd/limbo/ecom.c: ensure src set in temporary Node to avoid `no file specified' in sbl.[bc]
-20050925
- added format(2)
-20050922
- iostats(4) added
-20050919
- improve behaviour in wm/sh when in raw mode
-20050916
- /appl/lib/styx.b: return value for Rmsg.unpack for Rstat didn't include len[2]
-20050912
- update /appl/lib/disks.b, disks(2)
- update /appl/cmd/disk/format.b
- add /appl/cmd/disk/prep, /appl/cmd/disk/mbr.b
- replace format(8) by prep(8)
- delete undocumented /appl/cmd/disk/part.b
-20050908
- added disks(2) and scsiio(2)
-20050906
- os/port/devsrv.c and emu/port/devsrv.c to allow setting length by wstat (also DMAPPEND)
- appl/cmd/dossrv.b fix to interpret aname:offset
- usb updated to support current native uhci drivers
- /appl/lib/usb/usbmass.b changed to work with new driver and more devices
-20050901
- new /appl/cmd/ip/sntp.b, sntp(8)
-20050824
- cp(1): added -gux options
-20050810
- mangaload(8): new
-20050812
- /appl/cmd/limbo/nodes.b didn't always initialise n.c (eg, a != a)
-20050712
- updated utils/[12][acl] to match Plan 9's
-20050627
- added streamcp (renamed fcp since that's what plan 9 calls a similar thing)
-20050626
- added write lock to emu/port/devip.c to stop Linux (and perhaps others) splitting socket writes by different processes
-20050620
- added w3c-xpointers(2) [/module/xpointers.m; /appl/lib/w3c/xpointers.b]
-20050617
- fixed qid array reference in /appl/cmd/lockfs.b [cjones83]
-20050610
- updated lib/ndb/dns
- fixed count < 0 when reading beyond end of file in disk/kfs
-20050526
- fixed factotum's p9any to use user= attribute in key not /dev/user
- fix /appl/lib/daytime.b's handling of dlpairs; also read /env/timezone if that's there
- update /appl/lib/w3c/css.b to read CSS2.1
- add w3c-css(2); possibly should move module file to w3c/css.m?
-20050518
- added GPL/LGPL notice files
- made single mk.b from many included source files
- added MIT-template or LGPL NOTICE files to lib* directories
- updated doc/port.ms
- included libmp and libsec in lib/proto/src (Lucent Public License), not yet used
- fix bug in cmd(3) introduced by killonclose
-20050425
- add sexprs(6)
- add truerand/ntruerand and nsec[defined as osnsec] to lib9.h
- redefine fmax and log2 in lib9.h
- some/all FreeBSD-5.x-y don't initialise rfork_thread's procmask from parent (contrary to docs); compensate in FreeBSD/os.c
- finally copy last year's changes to 1c from home
- call logs->init in applylog
- changed /appl/cmd/cmp.b to work correctly for differing buffer sizes, errors, etc.
- included /os/pc/sd53c8xx.[in] and added /utils/na [not compiled by default]
- mask off OEXCL in (emu/port os/port)^/sysfile.c:/^kcreate's openmode
- wm/sh.b: keep menuitem 0 if noscroll selected
- added units(1)
-20050413
- licence following MIT-template replaces `free for all' instances
- "-N nice" option in os(1)
- geodesy(2) is new
- ebook(1) is newly released (Open Ebook browser)
- wm-sh(1) has a rearranged menu, with scroll/noscroll option added
- /doc/asm.ms has been updated
- section 10 has been updated
- limbo compiler will make simple functions inline if possible
- limbo compiler supports `ref fn' type
- /doc/limbo/addendum.ms [also .ps .pdf] updated to reflect `ref fn' and other changes
- keyring-ipint(2) has a few new operations (shl, shr, copy)
- DigestState has new copy operation replacing cloneDigestState
- Keyring has new functions certtoattr, pktoattr and sktoattr each returning
- a string containing attr=value ... representations of certificates and keys
- u.h has been updated for all platforms, hosted and native
- new ptrint, u8int, u16int, u64int, FPdbleword, and more accurate varargs for < 4 byte values
- lib9.h has extra encode/decode functions moved from libcrypt
- string.m has new quotec function [TODO: man page]
- crypt/ssl3.b handles a particular certificate type better
- charon has several bug fixes in javascript, notably parsing of certain expressions
- /doc/descent/* `Descent into Limbo' updated
- internally libinterp uses a different representation for parts of the linkage table
- /doc/lprof.ms [also .ps and .pdf] gives overview of Limbo profiling
- /doc/ebookimp.ms [also .ps and .pdf] discusses implementation of its XML browsing
- /doc/compiler.ms has been updated
- /doc/dis.ms eclr has been removed
- emu(1) -b enables bounds checking in JIT
- cs(8) handles general query (!attr=val ...)
- mkfs/mkext(8) handles big archives
- emuinit tries sh -c on command if not immediately dis
- /appl/lib/string.b: rewritten unquoted for correct handling of embedded quotes
- limbo warns about unused local variables
- limbo: -F enables new implementation of function ref
- limbo: -O runs optimiser
- mount -9 uses 9fs not styx as service address
- cmd(3) adds "killonclose" and parameter to "nice"
- TODO: group check in styxserver
- styxlisten accumulates algs correctly
- os/port/mkdevc builds vgacursor table
- touch uses OEXCL
- /appl/lib/debug knows about ref fn
- ecmascript: for(... in ...) parsed correctly
- getuserpasswd added to factotum(2)
- /appl/lib/print reincorporated
- wm/clock
- ftpfs calls factotum (getuserpasswd)
- hoststdin/hoststdout/hoststderr [preliminary]
- /os/boot/pc updated, as is its shipping list
-20041217
- base point
+ remove obsolete references to sh-exception( \ No newline at end of file
diff --git a/emu/port/devsrv.c b/emu/port/devsrv.c
index f655bf96..d98eb8e3 100644
--- a/emu/port/devsrv.c
+++ b/emu/port/devsrv.c
@@ -6,22 +6,39 @@
#include "runt.h"
typedef struct SrvFile SrvFile;
+typedef struct Pending Pending;
+
+/* request pending to a server, in case a server vanishes */
+struct Pending
+{
+ Pending* next;
+ Pending* prev;
+ int fid;
+ Channel* rc;
+ Channel* wc;
+};
+
struct SrvFile
{
- char* spec;
char* name;
char* user;
ulong perm;
- vlong length;
Qid qid;
int ref;
+
+ /* root directory */
+ char* spec;
+ SrvFile* devlist;
+ SrvFile* entry;
+
+ /* file */
int opens;
int flags;
+ vlong length;
Channel* read;
Channel* write;
- SrvFile* entry;
- SrvFile* dir;
- SrvFile* devlist;
+ SrvFile* dir; /* parent directory */
+ Pending waitlist; /* pending requests from client opens */
};
enum
@@ -47,6 +64,7 @@ static SrvDev dev;
void freechan(Heap*, int);
static void freerdchan(Heap*, int);
static void freewrchan(Heap*, int);
+static void delwaiting(Pending*);
Type *Trdchan;
Type *Twrchan;
@@ -98,7 +116,7 @@ srvinit(void)
}
static int
-srvchkattach(SrvFile *d)
+srvcanattach(SrvFile *d)
{
if(strcmp(d->user, up->env->user) == 0)
return 1;
@@ -119,47 +137,47 @@ srvattach(char *spec)
Chan *c;
SrvFile *d;
+ qlock(&dev.l);
+ if(waserror()){
+ qunlock(&dev.l);
+ nexterror();
+ }
+
if(spec[0] != '\0'){
- qlock(&dev.l);
for(d = dev.devices; d != nil; d = d->devlist){
if(strcmp(spec, d->spec) == 0){
- if(srvchkattach(d) == 0){
- qunlock(&dev.l);
+ if(!srvcanattach(d))
error(Eperm);
- }
+ c = devattach('s', spec);
+ c->aux = d;
+ c->qid = d->qid;
d->ref++;
- break;
+ poperror();
+ qunlock(&dev.l);
+ return c;
}
}
- qunlock(&dev.l);
-
- if(d != nil){
- c = devattach('s', spec);
- c->aux = d;
- c->qid = d->qid;
- return c;
- }
}
d = malloc(sizeof(SrvFile));
if(d == nil)
error(Enomem);
- c = devattach('s', spec);
-
d->ref = 1;
kstrdup(&d->spec, spec);
kstrdup(&d->user, up->env->user);
snprint(up->genbuf, sizeof(up->genbuf), "srv%ld", up->env->pgrp->pgrpid);
kstrdup(&d->name, up->genbuf);
d->perm = DMDIR|0770;
-
- qlock(&dev.l);
mkqid(&d->qid, dev.pathgen++, 0, QTDIR);
+
d->devlist = dev.devices;
dev.devices = d;
+
+ poperror();
qunlock(&dev.l);
+ c = devattach('s', spec);
c->aux = d;
c->qid = d->qid;
@@ -194,6 +212,7 @@ srvwalk(Chan *c, Chan *nc, char **name, int nname)
w->clone->aux = d;
d->ref++;
}
+
poperror();
qunlock(&dev.l);
return w;
@@ -294,23 +313,23 @@ srvwstat(Chan *c, uchar *dp, int n)
}
static void
-srvputdir(SrvFile *sf)
+srvputdir(SrvFile *dir)
{
SrvFile **l, *d;
- sf->ref--;
- if(sf->ref != 0)
+ dir->ref--;
+ if(dir->ref != 0)
return;
for(l = &dev.devices; (d = *l) != nil; l = &d->devlist)
- if(d == sf){
+ if(d == dir){
*l = d->devlist;
break;
}
- free(sf->spec);
- free(sf->user);
- free(sf->name);
- free(sf);
+ free(dir->spec);
+ free(dir->user);
+ free(dir->name);
+ free(dir);
}
static void
@@ -347,30 +366,59 @@ srvunblock(SrvFile *sf, int fid)
}
static void
-srvdecr(SrvFile *sf, int remove)
+srvcancelreqs(SrvFile *sf)
+{
+ Pending *w, *ws;
+ Sys_Rread rreply;
+ Sys_Rwrite wreply;
+
+ acquire();
+ ws = &sf->waitlist;
+ while((w = ws->next) != ws){
+ delwaiting(w);
+ if(waserror() == 0){
+ if(w->rc != nil){
+ rreply.t0 = H;
+ rreply.t1 = c2string(Ehungup, strlen(Ehungup));
+ csend(w->rc, &rreply);
+ }
+ if(w->wc != nil){
+ wreply.t0 = 0;
+ wreply.t1 = c2string(Ehungup, strlen(Ehungup));
+ csend(w->wc, &wreply);
+ }
+ poperror();
+ }
+ }
+ release();
+}
+
+static void
+srvdelete(SrvFile *sf)
{
SrvFile *f, **l;
- if(remove){
- l = &sf->dir->entry;
- for(f = *l; f != nil; f = f->entry){
+ if((sf->flags & SREMOVED) == 0){
+ for(l = &sf->dir->entry; (f = *l) != nil; l = &f->entry){
if(sf == f){
*l = f->entry;
break;
}
- l = &f->entry;
}
sf->ref--;
sf->flags |= SREMOVED;
}
+}
+static void
+srvchkref(SrvFile *sf)
+{
if(sf->ref != 0)
return;
if(sf->dir != nil)
srvputdir(sf->dir);
- free(sf->spec);
free(sf->user);
free(sf->name);
free(sf);
@@ -382,7 +430,10 @@ srvfree(SrvFile *sf, int flag)
sf->flags |= flag;
if((sf->flags & (SRDCLOSE | SWRCLOSE)) == (SRDCLOSE | SWRCLOSE)){
sf->ref--;
- srvdecr(sf, (sf->flags & SREMOVED) == 0);
+ srvdelete(sf);
+ /* no further requests can arrive; return error to pending requests */
+ srvcancelreqs(sf);
+ srvchkref(sf);
}
}
@@ -398,6 +449,7 @@ freerdchan(Heap *h, int swept)
srvfree(sf, SRDCLOSE);
qunlock(&dev.l);
acquire();
+
freechan(h, swept);
}
@@ -413,6 +465,7 @@ freewrchan(Heap *h, int swept)
srvfree(sf, SWRCLOSE);
qunlock(&dev.l);
acquire();
+
freechan(h, swept);
}
@@ -431,17 +484,16 @@ srvclunk(Chan *c, int remove)
error(Eperm);
return;
}
-
opens = 0;
if(c->flag & COPEN){
opens = sf->opens--;
- if (sf->read != H || sf->write != H)
+ if(sf->read != H || sf->write != H)
srvunblock(sf, c->fid);
}
sf->ref--;
if(opens == 1){
- if((sf->flags & (SORCLOSE | SREMOVED)) == SORCLOSE)
+ if(sf->flags & SORCLOSE)
remove = 1;
}
@@ -450,8 +502,9 @@ srvclunk(Chan *c, int remove)
noperm = 1;
remove = 0;
}
-
- srvdecr(sf, remove);
+ if(remove)
+ srvdelete(sf);
+ srvchkref(sf);
qunlock(&dev.l);
if(noperm)
@@ -470,6 +523,25 @@ srvremove(Chan *c)
srvclunk(c, 1);
}
+static void
+addwaiting(SrvFile *sp, Pending *w)
+{
+ Pending *sw;
+
+ sw = &sp->waitlist;
+ w->next = sw;
+ w->prev = sw->prev;
+ sw->prev->next = w;
+ sw->prev = w;
+}
+
+static void
+delwaiting(Pending *w)
+{
+ w->next->prev = w->prev;
+ w->prev->next = w->next;
+}
+
static long
srvread(Chan *c, void *va, long count, vlong offset)
{
@@ -479,6 +551,7 @@ srvread(Chan *c, void *va, long count, vlong offset)
SrvFile *sp;
Channel *rc;
Channel *rd;
+ Pending wait;
Sys_Rread * volatile r;
Sys_FileIO_read req;
@@ -504,7 +577,7 @@ srvread(Chan *c, void *va, long count, vlong offset)
rd = sp->read;
if(rd == H)
- error(Eshutdown);
+ error(Ehungup);
rc = cnewc(dev.Rread, movtmp, 1);
ptradd(D2H(rc));
@@ -520,16 +593,23 @@ srvread(Chan *c, void *va, long count, vlong offset)
req.t3 = rc;
csend(rd, &req);
+ wait.fid = c->fid;
+ wait.rc = rc;
+ wait.wc = nil;
+ addwaiting(sp, &wait);
+
h = heap(dev.Rread);
r = H2D(Sys_Rread *, h);
ptradd(h);
if(waserror()){
ptrdel(h);
destroy(r);
+ delwaiting(&wait);
nexterror();
}
crecv(rc, r);
+ delwaiting(&wait);
if(r->t1 != H)
error(string2c(r->t1));
@@ -564,6 +644,7 @@ srvwrite(Chan *c, void *va, long count, vlong offset)
SrvFile *sp;
Channel *wc;
Channel *wr;
+ Pending wait;
Sys_Rwrite * volatile w;
Sys_FileIO_write req;
@@ -579,7 +660,7 @@ srvwrite(Chan *c, void *va, long count, vlong offset)
sp = c->aux;
wr = sp->write;
if(wr == H)
- error(Eshutdown);
+ error(Ehungup);
wc = cnewc(dev.Rwrite, movtmp, 1);
ptradd(D2H(wc));
@@ -595,6 +676,7 @@ srvwrite(Chan *c, void *va, long count, vlong offset)
req.t3 = wc;
ptradd(D2H(req.t1));
+
if(waserror()){
ptrdel(D2H(req.t1));
destroy(req.t1);
@@ -610,12 +692,20 @@ srvwrite(Chan *c, void *va, long count, vlong offset)
h = heap(dev.Rwrite);
w = H2D(Sys_Rwrite *, h);
ptradd(h);
+
+ wait.fid = c->fid;
+ wait.rc = nil;
+ wait.wc = wc;
+ addwaiting(sp, &wait);
+
if(waserror()){
+ delwaiting(&wait);
ptrdel(h);
destroy(w);
nexterror();
}
crecv(wc, w);
+ delwaiting(&wait);
if(w->t1 != H)
error(string2c(w->t1));
poperror();
@@ -640,7 +730,7 @@ srvretype(Channel *c, SrvFile *f, Type *t)
Heap *h;
h = D2H(c);
- h->t->ref--;
+ freetype(h->t);
h->t = t;
t->ref++;
c->aux = f;
@@ -668,23 +758,26 @@ srvf2c(char *dir, char *file, Sys_FileIO *io)
s = c.c->aux;
qlock(&dev.l);
+ if(waserror()){
+ qunlock(&dev.l);
+ nexterror();
+ }
for(f = s->entry; f != nil; f = f->entry){
- if(strcmp(f->name, file) == 0){
- qunlock(&dev.l);
+ if(strcmp(f->name, file) == 0)
error(Eexist);
- }
}
f = malloc(sizeof(SrvFile));
- if(f == nil){
- qunlock(&dev.l);
+ if(f == nil)
error(Enomem);
- }
srvretype(io->read, f, Trdchan);
srvretype(io->write, f, Twrchan);
f->read = io->read;
f->write = io->write;
+
+ f->waitlist.next = &f->waitlist;
+ f->waitlist.prev = &f->waitlist;
kstrdup(&f->name, file);
kstrdup(&f->user, up->env->user);
@@ -697,6 +790,7 @@ srvf2c(char *dir, char *file, Sys_FileIO *io)
s->entry = f;
s->ref++;
f->dir = s;
+ poperror();
qunlock(&dev.l);
cclose(c.c);
diff --git a/man/3/srv b/man/3/srv
index 70261be4..74ec4586 100644
--- a/man/3/srv
+++ b/man/3/srv
@@ -84,5 +84,3 @@ is conventionally bound by various applications
.IR plumb (1),
.IR wm (1),
.IR sys-file2chan (2)
-.SH BUGS
-A client with a read or write pending can remain blocked if the server exits before reply.
diff --git a/os/port/devsrv.c b/os/port/devsrv.c
index 724e007e..707c690d 100644
--- a/os/port/devsrv.c
+++ b/os/port/devsrv.c
@@ -9,22 +9,39 @@
#include "runt.h"
typedef struct SrvFile SrvFile;
+typedef struct Pending Pending;
+
+/* request pending to a server, in case a server vanishes */
+struct Pending
+{
+ Pending* next;
+ Pending* prev;
+ int fid;
+ Channel* rc;
+ Channel* wc;
+};
+
struct SrvFile
{
- char* spec;
char* name;
char* user;
ulong perm;
- vlong length;
Qid qid;
int ref;
+
+ /* root directory */
+ char* spec;
+ SrvFile* devlist;
+ SrvFile* entry;
+
+ /* file */
int opens;
int flags;
+ vlong length;
Channel* read;
Channel* write;
- SrvFile* entry;
- SrvFile* dir;
- SrvFile* devlist;
+ SrvFile* dir; /* parent directory */
+ Pending waitlist; /* pending requests from client opens */
};
enum
@@ -50,15 +67,20 @@ static SrvDev dev;
void freechan(Heap*, int);
static void freerdchan(Heap*, int);
static void freewrchan(Heap*, int);
+static void delwaiting(Pending*);
Type *Trdchan;
Type *Twrchan;
static int
-srvgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
+srvgen(Chan *c, char *name, Dirtab *tab, int ntab, int s, Dir *dp)
{
SrvFile *f;
+ USED(name);
+ USED(tab);
+ USED(ntab);
+
if(s == DEVDOTDOT){
devdir(c, c->qid, "#s", 0, eve, 0555, dp);
return 1;
@@ -97,7 +119,7 @@ srvinit(void)
}
static int
-srvchkattach(SrvFile *d)
+srvcanattach(SrvFile *d)
{
if(strcmp(d->user, up->env->user) == 0)
return 1;
@@ -118,47 +140,47 @@ srvattach(char *spec)
Chan *c;
SrvFile *d;
+ qlock(&dev.l);
+ if(waserror()){
+ qunlock(&dev.l);
+ nexterror();
+ }
+
if(spec[0] != '\0'){
- qlock(&dev.l);
for(d = dev.devices; d != nil; d = d->devlist){
if(strcmp(spec, d->spec) == 0){
- if(srvchkattach(d) == 0){
- qunlock(&dev.l);
+ if(!srvcanattach(d))
error(Eperm);
- }
+ c = devattach('s', spec);
+ c->aux = d;
+ c->qid = d->qid;
d->ref++;
- break;
+ poperror();
+ qunlock(&dev.l);
+ return c;
}
}
- qunlock(&dev.l);
-
- if(d != nil){
- c = devattach('s', spec);
- c->aux = d;
- c->qid = d->qid;
- return c;
- }
}
d = malloc(sizeof(SrvFile));
if(d == nil)
error(Enomem);
- c = devattach('s', spec);
-
d->ref = 1;
kstrdup(&d->spec, spec);
kstrdup(&d->user, up->env->user);
snprint(up->genbuf, sizeof(up->genbuf), "srv%ld", up->env->pgrp->pgrpid);
kstrdup(&d->name, up->genbuf);
d->perm = DMDIR|0770;
-
- qlock(&dev.l);
mkqid(&d->qid, dev.pathgen++, 0, QTDIR);
+
d->devlist = dev.devices;
dev.devices = d;
+
+ poperror();
qunlock(&dev.l);
+ c = devattach('s', spec);
c->aux = d;
c->qid = d->qid;
@@ -193,6 +215,7 @@ srvwalk(Chan *c, Chan *nc, char **name, int nname)
w->clone->aux = d;
d->ref++;
}
+
poperror();
qunlock(&dev.l);
return w;
@@ -293,23 +316,23 @@ srvwstat(Chan *c, uchar *dp, int n)
}
static void
-srvputdir(SrvFile *sf)
+srvputdir(SrvFile *dir)
{
SrvFile **l, *d;
- sf->ref--;
- if(sf->ref != 0)
+ dir->ref--;
+ if(dir->ref != 0)
return;
for(l = &dev.devices; (d = *l) != nil; l = &d->devlist)
- if(d == sf){
+ if(d == dir){
*l = d->devlist;
break;
}
- free(sf->spec);
- free(sf->user);
- free(sf->name);
- free(sf);
+ free(dir->spec);
+ free(dir->user);
+ free(dir->name);
+ free(dir);
}
static void
@@ -346,30 +369,59 @@ srvunblock(SrvFile *sf, int fid)
}
static void
-srvdecr(SrvFile *sf, int remove)
+srvcancelreqs(SrvFile *sf)
+{
+ Pending *w, *ws;
+ Sys_Rread rreply;
+ Sys_Rwrite wreply;
+
+ acquire();
+ ws = &sf->waitlist;
+ while((w = ws->next) != ws){
+ delwaiting(w);
+ if(waserror() == 0){
+ if(w->rc != nil){
+ rreply.t0 = H;
+ rreply.t1 = c2string(Ehungup, strlen(Ehungup));
+ csend(w->rc, &rreply);
+ }
+ if(w->wc != nil){
+ wreply.t0 = 0;
+ wreply.t1 = c2string(Ehungup, strlen(Ehungup));
+ csend(w->wc, &wreply);
+ }
+ poperror();
+ }
+ }
+ release();
+}
+
+static void
+srvdelete(SrvFile *sf)
{
SrvFile *f, **l;
- if(remove){
- l = &sf->dir->entry;
- for(f = *l; f != nil; f = f->entry){
+ if((sf->flags & SREMOVED) == 0){
+ for(l = &sf->dir->entry; (f = *l) != nil; l = &f->entry){
if(sf == f){
*l = f->entry;
break;
}
- l = &f->entry;
}
sf->ref--;
sf->flags |= SREMOVED;
}
+}
+static void
+srvchkref(SrvFile *sf)
+{
if(sf->ref != 0)
return;
if(sf->dir != nil)
srvputdir(sf->dir);
- free(sf->spec);
free(sf->user);
free(sf->name);
free(sf);
@@ -381,7 +433,10 @@ srvfree(SrvFile *sf, int flag)
sf->flags |= flag;
if((sf->flags & (SRDCLOSE | SWRCLOSE)) == (SRDCLOSE | SWRCLOSE)){
sf->ref--;
- srvdecr(sf, (sf->flags & SREMOVED) == 0);
+ srvdelete(sf);
+ /* no further requests can arrive; return error to pending requests */
+ srvcancelreqs(sf);
+ srvchkref(sf);
}
}
@@ -397,6 +452,7 @@ freerdchan(Heap *h, int swept)
srvfree(sf, SRDCLOSE);
qunlock(&dev.l);
acquire();
+
freechan(h, swept);
}
@@ -412,6 +468,7 @@ freewrchan(Heap *h, int swept)
srvfree(sf, SWRCLOSE);
qunlock(&dev.l);
acquire();
+
freechan(h, swept);
}
@@ -430,17 +487,16 @@ srvclunk(Chan *c, int remove)
error(Eperm);
return;
}
-
opens = 0;
if(c->flag & COPEN){
opens = sf->opens--;
- if (sf->read != H || sf->write != H)
+ if(sf->read != H || sf->write != H)
srvunblock(sf, c->fid);
}
sf->ref--;
if(opens == 1){
- if((sf->flags & (SORCLOSE | SREMOVED)) == SORCLOSE)
+ if(sf->flags & SORCLOSE)
remove = 1;
}
@@ -449,8 +505,9 @@ srvclunk(Chan *c, int remove)
noperm = 1;
remove = 0;
}
-
- srvdecr(sf, remove);
+ if(remove)
+ srvdelete(sf);
+ srvchkref(sf);
qunlock(&dev.l);
if(noperm)
@@ -469,6 +526,25 @@ srvremove(Chan *c)
srvclunk(c, 1);
}
+static void
+addwaiting(SrvFile *sp, Pending *w)
+{
+ Pending *sw;
+
+ sw = &sp->waitlist;
+ w->next = sw;
+ w->prev = sw->prev;
+ sw->prev->next = w;
+ sw->prev = w;
+}
+
+static void
+delwaiting(Pending *w)
+{
+ w->next->prev = w->prev;
+ w->prev->next = w->next;
+}
+
static long
srvread(Chan *c, void *va, long count, vlong offset)
{
@@ -478,6 +554,7 @@ srvread(Chan *c, void *va, long count, vlong offset)
SrvFile *sp;
Channel *rc;
Channel *rd;
+ Pending wait;
Sys_Rread * volatile r;
Sys_FileIO_read req;
@@ -503,7 +580,7 @@ srvread(Chan *c, void *va, long count, vlong offset)
rd = sp->read;
if(rd == H)
- error(Eshutdown);
+ error(Ehungup);
rc = cnewc(dev.Rread, movtmp, 1);
ptradd(D2H(rc));
@@ -519,16 +596,23 @@ srvread(Chan *c, void *va, long count, vlong offset)
req.t3 = rc;
csend(rd, &req);
+ wait.fid = c->fid;
+ wait.rc = rc;
+ wait.wc = nil;
+ addwaiting(sp, &wait);
+
h = heap(dev.Rread);
r = H2D(Sys_Rread *, h);
ptradd(h);
if(waserror()){
ptrdel(h);
destroy(r);
+ delwaiting(&wait);
nexterror();
}
crecv(rc, r);
+ delwaiting(&wait);
if(r->t1 != H)
error(string2c(r->t1));
@@ -563,6 +647,7 @@ srvwrite(Chan *c, void *va, long count, vlong offset)
SrvFile *sp;
Channel *wc;
Channel *wr;
+ Pending wait;
Sys_Rwrite * volatile w;
Sys_FileIO_write req;
@@ -578,7 +663,7 @@ srvwrite(Chan *c, void *va, long count, vlong offset)
sp = c->aux;
wr = sp->write;
if(wr == H)
- error(Eshutdown);
+ error(Ehungup);
wc = cnewc(dev.Rwrite, movtmp, 1);
ptradd(D2H(wc));
@@ -594,6 +679,7 @@ srvwrite(Chan *c, void *va, long count, vlong offset)
req.t3 = wc;
ptradd(D2H(req.t1));
+
if(waserror()){
ptrdel(D2H(req.t1));
destroy(req.t1);
@@ -609,12 +695,20 @@ srvwrite(Chan *c, void *va, long count, vlong offset)
h = heap(dev.Rwrite);
w = H2D(Sys_Rwrite *, h);
ptradd(h);
+
+ wait.fid = c->fid;
+ wait.rc = nil;
+ wait.wc = wc;
+ addwaiting(sp, &wait);
+
if(waserror()){
+ delwaiting(&wait);
ptrdel(h);
destroy(w);
nexterror();
}
crecv(wc, w);
+ delwaiting(&wait);
if(w->t1 != H)
error(string2c(w->t1));
poperror();
@@ -639,7 +733,7 @@ srvretype(Channel *c, SrvFile *f, Type *t)
Heap *h;
h = D2H(c);
- h->t->ref--;
+ freetype(h->t);
h->t = t;
t->ref++;
c->aux = f;
@@ -667,23 +761,26 @@ srvf2c(char *dir, char *file, Sys_FileIO *io)
s = c.c->aux;
qlock(&dev.l);
+ if(waserror()){
+ qunlock(&dev.l);
+ nexterror();
+ }
for(f = s->entry; f != nil; f = f->entry){
- if(strcmp(f->name, file) == 0){
- qunlock(&dev.l);
+ if(strcmp(f->name, file) == 0)
error(Eexist);
- }
}
f = malloc(sizeof(SrvFile));
- if(f == nil){
- qunlock(&dev.l);
+ if(f == nil)
error(Enomem);
- }
srvretype(io->read, f, Trdchan);
srvretype(io->write, f, Twrchan);
f->read = io->read;
f->write = io->write;
+
+ f->waitlist.next = &f->waitlist;
+ f->waitlist.prev = &f->waitlist;
kstrdup(&f->name, file);
kstrdup(&f->user, up->env->user);
@@ -696,6 +793,7 @@ srvf2c(char *dir, char *file, Sys_FileIO *io)
s->entry = f;
s->ref++;
f->dir = s;
+ poperror();
qunlock(&dev.l);
cclose(c.c);