From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: QNX subprocess bug Date: Tue, 04 Apr 2006 18:55:34 -0400 Message-ID: <878xqlhs8m.fsf-monnier+emacs@gnu.org> References: <200604031800.k33I0DAv002355@copenhagen.cuug.ab.ca> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1144191373 24320 80.91.229.2 (4 Apr 2006 22:56:13 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Tue, 4 Apr 2006 22:56:13 +0000 (UTC) Cc: emacs-devel@gnu.org, rms@gnu.org, storm@cua.dk Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Apr 05 00:56:10 2006 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1FQuRQ-0001IV-7q for ged-emacs-devel@m.gmane.org; Wed, 05 Apr 2006 00:56:04 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1FQuRP-0006Fu-N8 for ged-emacs-devel@m.gmane.org; Tue, 04 Apr 2006 18:56:03 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1FQuRA-0006FX-O6 for emacs-devel@gnu.org; Tue, 04 Apr 2006 18:55:48 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1FQuR9-0006FL-KC for emacs-devel@gnu.org; Tue, 04 Apr 2006 18:55:48 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1FQuR9-0006FI-F0 for emacs-devel@gnu.org; Tue, 04 Apr 2006 18:55:47 -0400 Original-Received: from [209.226.175.188] (helo=tomts25-srv.bellnexxia.net) by monty-python.gnu.org with esmtp (Exim 4.52) id 1FQuUM-0007gU-Hi; Tue, 04 Apr 2006 18:59:06 -0400 Original-Received: from alfajor ([70.53.193.73]) by tomts25-srv.bellnexxia.net (InterMail vM.5.01.06.13 201-253-122-130-113-20050324) with ESMTP id <20060404225534.WEOT28586.tomts25-srv.bellnexxia.net@alfajor>; Tue, 4 Apr 2006 18:55:34 -0400 Original-Received: by alfajor (Postfix, from userid 1000) id 5F68BD78D4; Tue, 4 Apr 2006 18:55:34 -0400 (EDT) Original-To: bob In-Reply-To: <200604031800.k33I0DAv002355@copenhagen.cuug.ab.ca> (bob@copenhagen.cuug.ab.ca's message of "Mon, 3 Apr 2006 12:00:08 -0600 (MDT)") User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:52419 Archived-At: > I have observed PIDs very high in the 32-bit space (most user processes) > and quite low (most system processes) and very little in between. > Right now I don't have access to my QNX system so I can't give you any > real examples. QNX is not open source so there is no obvious way to tell > how the PIDs get generated. > The float (I take it we're talking "double" here) sounds like the > best solution. I'll hack it into the code and see what happens. I think the best solution is to keep pid_t values (without changing them into Lisp_Object values) as long as possible, and to use floats when turning them into Lisp_Object. The patch below does just that. It has been lightly tested. Stefan * looking for monnier@iro.umontreal.ca--first/emacs--monnier--0--patch-347 to compare with * comparing to monnier@iro.umontreal.ca--first/emacs--monnier--0--patch-347 M src/process.c M src/alloc.c M src/lisp.h M src/process.h * modified files --- orig/src/process.h +++ mod/src/process.h @@ -51,8 +51,6 @@ Lisp_Object log; /* Buffer that output is going to */ Lisp_Object buffer; - /* Number of this process */ - Lisp_Object pid; /* t if this is a real child process. For a net connection, it is a plist based on the arguments to make-network-process. */ Lisp_Object childp; @@ -63,10 +61,6 @@ /* Non-nil means kill silently if Emacs is exited. This is the inverse of the `query-on-exit' flag. */ Lisp_Object kill_without_query; - /* Record the process status in the raw form in which it comes from `wait'. - This is to avoid consing in a signal handler. */ - Lisp_Object raw_status_low; - Lisp_Object raw_status_high; /* Symbol indicating status of process. This may be a symbol: run, open, or closed. Or it may be a list, whose car is stop, exit or signal @@ -75,10 +69,6 @@ Lisp_Object status; /* Non-nil if communicating through a pty. */ Lisp_Object pty_flag; - /* Event-count of last event in which this process changed status. */ - Lisp_Object tick; - /* Event-count of last such event reported. */ - Lisp_Object update_tick; /* Coding-system for decoding the input from this process. */ Lisp_Object decode_coding_system; /* Working buffer for decoding. */ @@ -112,6 +102,21 @@ Lisp_Object read_output_delay; /* Skip reading this process on next read. */ Lisp_Object read_output_skip; + + /* After this point, there are no Lisp_Objects any more. */ + + /* Number of this process. + allocate_process assumes this is the first non-Lisp_Objects field. + A value 0 is used for pseudo-processes such as network connections. */ + pid_t pid; + /* Record the process status in the raw form in which it comes from `wait'. + This is to avoid consing in a signal handler. */ + int raw_status_new : 1; + int raw_status; + /* Event-count of last event in which this process changed status. */ + int tick; + /* Event-count of last such event reported. */ + int update_tick; }; /* Every field in the preceding structure except for the first two --- orig/src/lisp.h +++ mod/src/lisp.h @@ -746,6 +746,20 @@ + sizeof(Lisp_Object) - 1) /* round up */ \ / sizeof (Lisp_Object)) +#ifdef offsetof +#define OFFSETOF(type,field) offsetof(type,field) +#else +#define OFFSETOF(type,field) \ + ((int)((char*)&((type*)0)->field - (char*)0)) +#endif + +/* Like VECSIZE, but used when the pseudo-vector has non-Lisp_Object fields + at the end and we need to compute the number of Lisp_Object fields (the + ones that the GC needs to trace). */ +#define SPECVECSIZE(type, nonlispfield) \ + ((offsetof(type, nonlispfield) - offsetof(struct Lisp_Vector, contents[0])) \ + / sizeof (Lisp_Object)) + struct Lisp_Vector { EMACS_INT size; --- orig/src/alloc.c +++ mod/src/alloc.c @@ -3069,13 +3069,14 @@ struct Lisp_Process * allocate_process () { - EMACS_INT len = VECSIZE (struct Lisp_Process); - struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_PROCESS); + EMACS_INT memlen = VECSIZE (struct Lisp_Process); + EMACS_INT lisplen = SPECVECSIZE (struct Lisp_Process, pid); + struct Lisp_Vector *v = allocate_vectorlike (memlen, MEM_TYPE_PROCESS); EMACS_INT i; - for (i = 0; i < len; ++i) + for (i = 0; i < lisplen; ++i) v->contents[i] = Qnil; - v->size = len; + v->size = lisplen; return (struct Lisp_Process *) v; } --- orig/src/process.c +++ mod/src/process.c @@ -415,10 +415,10 @@ struct Lisp_Process *p; { union { int i; WAITTYPE wt; } u; - u.i = XFASTINT (p->raw_status_low) + (XFASTINT (p->raw_status_high) << 16); + eassert (p->raw_status_new); + u.i = p->raw_status; p->status = status_convert (u.wt); - p->raw_status_low = Qnil; - p->raw_status_high = Qnil; + p->raw_status_new = 0; } /* Convert a process status word in Unix format to @@ -620,11 +620,10 @@ XSETINT (p->infd, -1); XSETINT (p->outfd, -1); - XSETFASTINT (p->pid, 0); - XSETFASTINT (p->tick, 0); - XSETFASTINT (p->update_tick, 0); - p->raw_status_low = Qnil; - p->raw_status_high = Qnil; + p->pid = 0; + p->tick = 0; + p->update_tick = 0; + p->raw_status_new = 0; p->status = Qrun; p->mark = Fmake_marker (); @@ -790,12 +789,11 @@ process = get_process (process); p = XPROCESS (process); - p->raw_status_low = Qnil; - p->raw_status_high = Qnil; + p->raw_status_new = 0; if (NETCONN1_P (p)) { p->status = Fcons (Qexit, Fcons (make_number (0), Qnil)); - XSETINT (p->tick, ++process_tick); + p->tick = ++process_tick; status_notify (p); } else if (XINT (p->infd) >= 0) @@ -804,7 +802,7 @@ /* Do this now, since remove_process will make sigchld_handler do nothing. */ p->status = Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil)); - XSETINT (p->tick, ++process_tick); + p->tick = ++process_tick; status_notify (p); } remove_process (process); @@ -841,7 +839,7 @@ return process; p = XPROCESS (process); - if (!NILP (p->raw_status_low)) + if (p->raw_status_new) update_status (p); status = p->status; if (CONSP (status)) @@ -866,7 +864,7 @@ register Lisp_Object process; { CHECK_PROCESS (process); - if (!NILP (XPROCESS (process)->raw_status_low)) + if (XPROCESS (process)->raw_status_new) update_status (XPROCESS (process)); if (CONSP (XPROCESS (process)->status)) return XCAR (XCDR (XPROCESS (process)->status)); @@ -881,7 +879,9 @@ register Lisp_Object process; { CHECK_PROCESS (process); - return XPROCESS (process)->pid; + return (XPROCESS (process)->pid + ? make_fixnum_or_float (XPROCESS (process)->pid) + : Qnil); } DEFUN ("process-name", Fprocess_name, Sprocess_name, 1, 1, 0, @@ -1363,7 +1363,7 @@ Finsert (1, &p->name); Findent_to (i_status, minspace); - if (!NILP (p->raw_status_low)) + if (p->raw_status_new) update_status (p); symbol = p->status; if (CONSP (p->status)) @@ -1735,7 +1735,7 @@ abort (); /* Was PROC started successfully? */ - if (XINT (XPROCESS (proc)->pid) <= 0) + if (XPROCESS (proc)->pid <= 0) remove_process (proc); return Qnil; @@ -1946,7 +1946,7 @@ in the table after this function has returned; if it does it might cause call-process to hang and subsequent asynchronous processes to get their return values scrambled. */ - XSETINT (XPROCESS (process)->pid, -1); + XPROCESS (process)->pid = -1; BLOCK_INPUT; @@ -2137,7 +2137,7 @@ else { /* vfork succeeded. */ - XSETFASTINT (XPROCESS (process)->pid, pid); + XPROCESS (process)->pid = pid; #ifdef WINDOWSNT register_child (pid, inchannel); @@ -3350,7 +3350,7 @@ p->kill_without_query = Qt; if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) p->command = Qt; - p->pid = Qnil; + p->pid = 0; XSETINT (p->infd, inch); XSETINT (p->outfd, outch); if (is_server && socktype == SOCK_STREAM) @@ -4066,7 +4066,7 @@ p->sentinel = ps->sentinel; p->filter = ps->filter; p->command = Qnil; - p->pid = Qnil; + p->pid = 0; XSETINT (p->infd, s); XSETINT (p->outfd, s); p->status = Qrun; @@ -4369,9 +4369,9 @@ /* Don't wait for output from a non-running process. Just read whatever data has already been received. */ - if (wait_proc != 0 && !NILP (wait_proc->raw_status_low)) + if (wait_proc && wait_proc->raw_status_new) update_status (wait_proc); - if (wait_proc != 0 + if (wait_proc && ! EQ (wait_proc->status, Qrun) && ! EQ (wait_proc->status, Qconnect)) { @@ -4753,9 +4753,9 @@ else { /* Preserve status of processes already terminated. */ - XSETINT (XPROCESS (proc)->tick, ++process_tick); + XPROCESS (proc)->tick = ++process_tick; deactivate_process (proc); - if (!NILP (XPROCESS (proc)->raw_status_low)) + if (XPROCESS (proc)->raw_status_new) update_status (XPROCESS (proc)); if (EQ (XPROCESS (proc)->status, Qrun)) XPROCESS (proc)->status @@ -4805,7 +4805,7 @@ #endif if (xerrno) { - XSETINT (p->tick, ++process_tick); + p->tick = ++process_tick; p->status = Fcons (Qfailed, Fcons (make_number (xerrno), Qnil)); deactivate_process (proc); } @@ -5292,7 +5292,7 @@ VMS_PROC_STUFF *vs, *get_vms_process_pointer(); #endif /* VMS */ - if (! NILP (p->raw_status_low)) + if (p->raw_status_new) update_status (p); if (! EQ (p->status, Qrun)) error ("Process %s not running", SDATA (p->name)); @@ -5556,10 +5556,9 @@ proc = process_sent_to; p = XPROCESS (proc); #endif - p->raw_status_low = Qnil; - p->raw_status_high = Qnil; + p->raw_status_new = 0; p->status = Fcons (Qexit, Fcons (make_number (256), Qnil)); - XSETINT (p->tick, ++process_tick); + p->tick = ++process_tick; deactivate_process (proc); #ifdef VMS error ("Error writing to process %s; closed it", SDATA (p->name)); @@ -5672,7 +5671,7 @@ gid = emacs_get_tty_pgrp (p); - if (gid == XFASTINT (p->pid)) + if (gid == p->pid) return Qnil; return Qt; } @@ -5719,7 +5718,7 @@ /* If we are using pgrps, get a pgrp number and make it negative. */ if (NILP (current_group)) /* Send the signal to the shell's process group. */ - gid = XFASTINT (p->pid); + gid = p->pid; else { #ifdef SIGNALS_VIA_CHARACTERS @@ -5838,7 +5837,7 @@ if (gid == -1) /* If we can't get the information, assume the shell owns the tty. */ - gid = XFASTINT (p->pid); + gid = p->pid; /* It is not clear whether anything really can set GID to -1. Perhaps on some system one of those ioctls can or could do so. @@ -5848,12 +5847,12 @@ #else /* ! defined (TIOCGPGRP ) */ /* Can't select pgrps on this system, so we know that the child itself heads the pgrp. */ - gid = XFASTINT (p->pid); + gid = p->pid; #endif /* ! defined (TIOCGPGRP ) */ /* If current_group is lambda, and the shell owns the terminal, don't send any signal. */ - if (EQ (current_group, Qlambda) && gid == XFASTINT (p->pid)) + if (EQ (current_group, Qlambda) && gid == p->pid) return; } @@ -5861,10 +5860,9 @@ { #ifdef SIGCONT case SIGCONT: - p->raw_status_low = Qnil; - p->raw_status_high = Qnil; + p->raw_status_new = 0; p->status = Qrun; - XSETINT (p->tick, ++process_tick); + p->tick = ++process_tick; if (!nomsg) status_notify (NULL); break; @@ -5881,7 +5879,7 @@ #endif case SIGKILL: #ifdef VMS - sys$forcex (&(XFASTINT (p->pid)), 0, 1); + sys$forcex (&(p->pid), 0, 1); whoosh: #endif flush_pending_output (XINT (p->infd)); @@ -5893,7 +5891,7 @@ obvious alternative. */ if (no_pgrp) { - kill (XFASTINT (p->pid), signo); + kill (p->pid, signo); return; } @@ -5906,7 +5904,7 @@ } else { - gid = - XFASTINT (p->pid); + gid = - p->pid; kill (gid, signo); } #else /* ! defined (TIOCSIGSEND) */ @@ -6026,11 +6024,17 @@ (process, sigcode) Lisp_Object process, sigcode; { - Lisp_Object pid; + pid_t pid; if (INTEGERP (process)) { - pid = process; + pid = XINT (process); + goto got_it; + } + + if (FLOATP (process)) + { + pid = (pid_t) XFLOAT (process); goto got_it; } @@ -6039,8 +6043,8 @@ Lisp_Object tem; if (tem = Fget_process (process), NILP (tem)) { - pid = Fstring_to_number (process, make_number (10)); - if (XINT (pid) != 0) + pid = XINT (Fstring_to_number (process, make_number (10))); + if (pid > 0) goto got_it; } process = tem; @@ -6053,7 +6057,7 @@ CHECK_PROCESS (process); pid = XPROCESS (process)->pid; - if (!INTEGERP (pid) || XINT (pid) <= 0) + if (pid <= 0) error ("Cannot signal process %s", SDATA (XPROCESS (process)->name)); got_it: @@ -6172,7 +6176,7 @@ #undef handle_signal - return make_number (kill (XINT (pid), XINT (sigcode))); + return make_number (kill (pid, XINT (sigcode))); } DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0, @@ -6196,7 +6200,7 @@ coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)]; /* Make sure the process is really alive. */ - if (! NILP (XPROCESS (proc)->raw_status_low)) + if (XPROCESS (proc)->raw_status_new) update_status (XPROCESS (proc)); if (! EQ (XPROCESS (proc)->status, Qrun)) error ("Process %s not running", SDATA (XPROCESS (proc)->name)); @@ -6221,7 +6225,7 @@ for communication with the subprocess, call shutdown to cause EOF. (In some old system, shutdown to socketpair doesn't work. Then we just can't win.) */ - if (NILP (XPROCESS (proc)->pid) + if (XPROCESS (proc)->pid == 0 || XINT (XPROCESS (proc)->outfd) == XINT (XPROCESS (proc)->infd)) shutdown (XINT (XPROCESS (proc)->outfd), 1); /* In case of socketpair, outfd == infd, so don't close it. */ @@ -6358,7 +6362,7 @@ { proc = XCDR (XCAR (tail)); p = XPROCESS (proc); - if (GC_EQ (p->childp, Qt) && XINT (p->pid) == pid) + if (GC_EQ (p->childp, Qt) && p->pid == pid) break; p = 0; } @@ -6370,7 +6374,7 @@ { proc = XCDR (XCAR (tail)); p = XPROCESS (proc); - if (GC_INTEGERP (p->pid) && XINT (p->pid) == -1) + if (p->pid == -1) break; p = 0; } @@ -6381,10 +6385,10 @@ union { int i; WAITTYPE wt; } u; int clear_desc_flag = 0; - XSETINT (p->tick, ++process_tick); + p->tick = ++process_tick; u.wt = w; - XSETINT (p->raw_status_low, u.i & 0xffff); - XSETINT (p->raw_status_high, u.i >> 16); + p->raw_status = u.i; + p->raw_status_new = 1; /* If process has terminated, stop waiting for its output. */ if ((WIFSIGNALED (w) || WIFEXITED (w)) @@ -6565,9 +6569,9 @@ proc = Fcdr (XCAR (tail)); p = XPROCESS (proc); - if (XINT (p->tick) != XINT (p->update_tick)) + if (p->tick != p->update_tick) { - XSETINT (p->update_tick, XINT (p->tick)); + p->update_tick = p->tick; /* If process is still active, read any output that remains. */ while (! EQ (p->filter, Qt) @@ -6581,7 +6585,7 @@ buffer = p->buffer; /* Get the text to use for the message. */ - if (!NILP (p->raw_status_low)) + if (p->raw_status_new) update_status (p); msg = status_message (p); @@ -6603,7 +6607,7 @@ So set p->update_tick again so that an error in the sentinel will not cause this code to be run again. */ - XSETINT (p->update_tick, XINT (p->tick)); + p->update_tick = p->tick; /* Now output the message suitably. */ if (!NILP (p->sentinel)) exec_sentinel (proc, msg);