post.c 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <fcall.h>
  4. #include <thread.h>
  5. #include <9p.h>
  6. #include <auth.h>
  7. static void postproc(void*);
  8. void
  9. _postmountsrv(Srv *s, char *name, char *mtpt, int flag)
  10. {
  11. int fd[2];
  12. if(!s->nopipe){
  13. if(pipe(fd) < 0)
  14. sysfatal("pipe: %r");
  15. s->infd = s->outfd = fd[1];
  16. s->srvfd = fd[0];
  17. }
  18. if(name)
  19. if(postfd(name, s->srvfd) < 0)
  20. sysfatal("postfd %s: %r", name);
  21. if(_forker == nil)
  22. sysfatal("no forker");
  23. _forker(postproc, s, RFNAMEG);
  24. /*
  25. * Normally the server is posting as the last thing it does
  26. * before exiting, so the correct thing to do is drop into
  27. * a different fd space and close the 9P server half of the
  28. * pipe before trying to mount the kernel half. This way,
  29. * if the file server dies, we don't have a ref to the 9P server
  30. * half of the pipe. Then killing the other procs will drop
  31. * all the refs on the 9P server half, and the mount will fail.
  32. * Otherwise the mount hangs forever.
  33. *
  34. * Libthread in general and acme win in particular make
  35. * it hard to make this fd bookkeeping work out properly,
  36. * so leaveinfdopen is a flag that win sets to opt out of this
  37. * safety net.
  38. */
  39. if(!s->leavefdsopen){
  40. rfork(RFFDG);
  41. rendezvous(0, 0);
  42. close(s->infd);
  43. if(s->infd != s->outfd)
  44. close(s->outfd);
  45. }
  46. if(mtpt){
  47. if(amount(s->srvfd, mtpt, flag, "") == -1)
  48. sysfatal("mount %s: %r", mtpt);
  49. }else
  50. close(s->srvfd);
  51. }
  52. static void
  53. postproc(void *v)
  54. {
  55. Srv *s;
  56. s = v;
  57. if(!s->leavefdsopen){
  58. rfork(RFNOTEG);
  59. rendezvous(0, 0);
  60. close(s->srvfd);
  61. }
  62. srv(s);
  63. }