proc.scm 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Marcus Crestani,
  3. ; Will Noble, Roderic Morris
  4. ; 3.1 Process Creation and Execution
  5. (import-dynamic-externals "=scheme48external/posix")
  6. ;
  7. ; FORK returns the child pid in the parent, and #f in the child.
  8. (define (fork)
  9. (force-channel-output-ports!)
  10. (let ((pid (posix-fork)))
  11. (and (> pid 0) (enter-pid pid))))
  12. (import-lambda-definition-2 posix-fork ())
  13. ; Fork off a process to execute THUNK, but don't return a pid. This avoids
  14. ; any problem with zombies.
  15. (define (fork-and-forget thunk)
  16. (cond ((fork)
  17. => wait-for-child-process)
  18. ((fork)
  19. (exit 0))
  20. (else
  21. (thunk))))
  22. ;----------------
  23. ; The base Scheme procedure for exec() is EXEC-WITH-ALIAS (the `alias' is
  24. ; because the first argument may or may not be the name of the program or file).
  25. ;
  26. ; (EXEC-WITH-ALIAS program lookup? environment arguments)
  27. ; program: byte vector, name of file or program
  28. ; lookup?: should the program be looked up in PATH?
  29. ; environment: either #f, which uses the parent's environment in the child,
  30. ; or a list of byte vectors, representing text of the form "name=value".
  31. ; arguments: a list of byte vectors
  32. (import-lambda-definition-2 external-exec-with-alias (program lookup? environment arguments)
  33. "posix_exec")
  34. (define (thing->exec-arg-byte-string thing)
  35. (x->os-byte-vector thing))
  36. (define (exec-with-alias program lookup? environment arguments)
  37. (external-exec-with-alias (thing->exec-arg-byte-string program)
  38. lookup?
  39. (and environment
  40. (map thing->exec-arg-byte-string environment))
  41. (map thing->exec-arg-byte-string arguments)))
  42. ; Four versions of exec():
  43. ; - program looked up, use default environment
  44. ; - program looked up, environment argument
  45. ; - file used as-is, use default environment
  46. ; - file used as-is, environment argument
  47. ;
  48. ; In all cases, the program or file is added to the beginning of the list
  49. ; of arguments.
  50. ;
  51. ; When given, ENV should be a list of strings of the form "name=value".
  52. (define (exec program . arguments)
  53. (exec-with-alias program #t #f (cons program arguments)))
  54. (define (exec-with-environment program env . arguments)
  55. (exec-with-alias program #t env (cons program arguments)))
  56. (define (exec-file file . arguments)
  57. (exec-with-alias file #f #f (cons file arguments)))
  58. (define (exec-file-with-environment file env . arguments)
  59. (exec-with-alias file #f env (cons file arguments)))
  60. ;----------------
  61. ; Process ids
  62. ;
  63. ; Threads can wait for child process to terminate. This requires polling,
  64. ; which in turn requires that we store the child's return status or terminating
  65. ; signal for later use. Hence the extra fields.
  66. ;
  67. ; These should probably not be dumpable.
  68. ;
  69. ; Because these have state they must be unique. The C code keeps a weak
  70. ; list of existing ones.
  71. (define-record-type process-id :process-id
  72. (make-process-id uid exit-status terminating-signal placeholder)
  73. process-id?
  74. (uid process-id->integer) ; the Unix PID
  75. ; The rest are initially #F and are set as events warrant.
  76. (exit-status process-id-exit-status set-process-id-exit-status!)
  77. (terminating-signal process-id-terminating-signal set-process-id-terminating-signal!)
  78. (placeholder process-id-placeholder))
  79. (define-record-discloser :process-id
  80. (lambda (process-id)
  81. (list 'process-id (process-id->integer process-id))))
  82. ; Invalidate process IDs on resuming image.
  83. (define-record-resumer :process-id #f)
  84. (define *process-ids* (make-population))
  85. (define-reinitializer process-id-reinitializer
  86. (lambda () (set! *process-ids* (make-population))))
  87. (define (process-id=? p1 p2)
  88. (if (and (process-id? p1)
  89. (process-id? p2))
  90. (eq? p1 p2)
  91. (assertion-violation 'process-id=? "argument type error" p1 p2)))
  92. (define (enter-pid num)
  93. (let ((pid (make-process-id num #f #f (make-placeholder))))
  94. (add-to-population! pid *process-ids*)
  95. pid))
  96. (define (lookup-pid num)
  97. (call-with-current-continuation
  98. (lambda (return)
  99. (walk-population
  100. (lambda (pid)
  101. (if (= num (process-id->integer pid)) (return pid)))
  102. *process-ids*)
  103. #f)))
  104. (define (integer->process-id num) (or (lookup-pid num) (enter-pid num)))
  105. ;----------------
  106. ; 3.2 Process Termination
  107. ;
  108. ; pid_t wait(int *stat_loc)
  109. ; pid_t waitpid(pid_t pid, int *stat_loc, int options)
  110. ; void _exit(int status); Need to do this.
  111. ; Wait for a child process.
  112. (define (wait-for-child-process pid)
  113. (placeholder-value (process-id-placeholder pid) #f)
  114. (values))
  115. ; Waiting for children. We go through the terminated child processes
  116. ; until we we run out. This needs to be called by the SIGCHLD
  117. ; handler.
  118. (define (process-terminated-children)
  119. (let loop ()
  120. (cond
  121. ((posix-waitpid)
  122. => (lambda (next)
  123. (cond
  124. ((lookup-pid (vector-ref next 0))
  125. => (lambda (pid)
  126. (set-process-id-exit-status! pid (vector-ref next 1))
  127. (set-process-id-terminating-signal!
  128. pid
  129. (and (vector-ref next 2)
  130. (integer->signal (vector-ref next 2))))
  131. (placeholder-set! (process-id-placeholder pid) #t))))
  132. (loop))))))
  133. (import-lambda-definition-2 posix-waitpid ())
  134. (define (exit status)
  135. (force-channel-output-ports!)
  136. (scheme-exit-now status))