mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	Store errno in struct rb_process_status
To propagate errno in the fiber thread scheduler hook. Returns nil when no terminated process.
This commit is contained in:
		
							parent
							
								
									c752d29bbf
								
							
						
					
					
						commit
						bdbbfd1fa5
					
				
				
				Notes:
				
					git
				
				2020-12-24 23:00:01 +09:00 
				
			
			
			
		
		
					 2 changed files with 37 additions and 17 deletions
				
			
		
							
								
								
									
										37
									
								
								process.c
									
										
									
									
									
								
							
							
						
						
									
										37
									
								
								process.c
									
										
									
									
									
								
							|  | @ -572,6 +572,7 @@ static VALUE rb_cProcessStatus; | |||
| struct rb_process_status { | ||||
|     rb_pid_t pid; | ||||
|     int status; | ||||
|     int error; | ||||
| }; | ||||
| 
 | ||||
| static const rb_data_type_t rb_process_status_type = { | ||||
|  | @ -619,13 +620,14 @@ proc_s_last_status(VALUE mod) | |||
| } | ||||
| 
 | ||||
| VALUE | ||||
| rb_process_status_new(rb_pid_t pid, int status) | ||||
| rb_process_status_new(rb_pid_t pid, int status, int error) | ||||
| { | ||||
|     VALUE last_status = rb_process_status_allocate(rb_cProcessStatus); | ||||
| 
 | ||||
|     struct rb_process_status *data = RTYPEDDATA_DATA(last_status); | ||||
|     data->pid = pid; | ||||
|     data->status = status; | ||||
|     data->error = error; | ||||
| 
 | ||||
|     rb_obj_freeze(last_status); | ||||
|     return last_status; | ||||
|  | @ -657,7 +659,7 @@ process_status_load(VALUE real_obj, VALUE load_obj) | |||
| void | ||||
| rb_last_status_set(int status, rb_pid_t pid) | ||||
| { | ||||
|     GET_THREAD()->last_status = rb_process_status_new(pid, status); | ||||
|     GET_THREAD()->last_status = rb_process_status_new(pid, status, 0); | ||||
| } | ||||
| 
 | ||||
| void | ||||
|  | @ -1164,6 +1166,7 @@ waitpid_state_init(struct waitpid_state *w, rb_pid_t pid, int options) | |||
|     w->pid = pid; | ||||
|     w->options = options; | ||||
|     w->errnum = 0; | ||||
|     w->status = 0; | ||||
| } | ||||
| 
 | ||||
| static const rb_hrtime_t * | ||||
|  | @ -1349,20 +1352,17 @@ rb_process_status_wait(rb_pid_t pid, int flags) | |||
|         waitpid_no_SIGCHLD(w); | ||||
|     } | ||||
| 
 | ||||
|     VALUE status = Qnil; | ||||
|     if (w->ret == -1) { | ||||
|         errno = w->errnum; | ||||
|     } | ||||
|     else if (w->ret > 0 && ruby_nocldwait) { | ||||
|         errno = ECHILD; | ||||
|     } | ||||
|     else { | ||||
|         status = rb_process_status_new(w->ret, w->status); | ||||
|     } | ||||
| 
 | ||||
|     rb_pid_t ret = w->ret; | ||||
|     int s = w->status, e = w->errnum; | ||||
|     COROUTINE_STACK_FREE(w); | ||||
| 
 | ||||
|     return status; | ||||
|     if (ret == 0) return Qnil; | ||||
|     if (ret > 0 && ruby_nocldwait) { | ||||
|         ret = -1; | ||||
|         e = ECHILD; | ||||
|     } | ||||
| 
 | ||||
|     return rb_process_status_new(ret, s, e); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -1432,14 +1432,19 @@ rb_pid_t | |||
| rb_waitpid(rb_pid_t pid, int *st, int flags) | ||||
| { | ||||
|     VALUE status = rb_process_status_wait(pid, flags); | ||||
|     if (NIL_P(status)) return -1; | ||||
|     if (NIL_P(status)) return 0; | ||||
| 
 | ||||
|     struct rb_process_status *data = RTYPEDDATA_DATA(status); | ||||
|     pid = data->pid; | ||||
| 
 | ||||
|     if (st) *st = data->status; | ||||
| 
 | ||||
|     GET_THREAD()->last_status = status; | ||||
|     if (pid == -1) { | ||||
|         errno = data->error; | ||||
|     } | ||||
|     else { | ||||
|         GET_THREAD()->last_status = status; | ||||
|     } | ||||
| 
 | ||||
|     return pid; | ||||
| } | ||||
|  |  | |||
|  | @ -1466,7 +1466,22 @@ class TestProcess < Test::Unit::TestCase | |||
|   end | ||||
| 
 | ||||
|   def test_status_fail | ||||
|     assert_nil(Process::Status.wait($$)) | ||||
|     ret = Process::Status.wait($$) | ||||
|     assert_instance_of(Process::Status, ret) | ||||
|     assert_equal(-1, ret.pid) | ||||
|   end | ||||
| 
 | ||||
| 
 | ||||
|   def test_status_wait | ||||
|     IO.popen([RUBY, "-e", "gets"], "w") do |io| | ||||
|       pid = io.pid | ||||
|       assert_nil(Process::Status.wait(pid, Process::WNOHANG)) | ||||
|       io.puts | ||||
|       ret = Process::Status.wait(pid) | ||||
|       assert_instance_of(Process::Status, ret) | ||||
|       assert_equal(pid, ret.pid) | ||||
|       assert_predicate(ret, :exited?) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def test_wait_without_arg | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Nobuyoshi Nakada
						Nobuyoshi Nakada