Mercurial > hg > xemacs-beta
diff src/ntproc.c @ 282:c42ec1d1cded r21-0b39
Import from CVS: tag r21-0b39
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:33:18 +0200 |
parents | ca9a9ec9c1c1 |
children | e11d67e05968 |
line wrap: on
line diff
--- a/src/ntproc.c Mon Aug 13 10:32:23 2007 +0200 +++ b/src/ntproc.c Mon Aug 13 10:33:18 2007 +0200 @@ -327,7 +327,11 @@ cp->pid = -cp->pid; /* pid must fit in a Lisp_Int */ +#ifdef USE_UNION_TYPE + cp->pid = (cp->pid & ((1U << VALBITS) - 1)); +#else cp->pid = (cp->pid & VALMASK); +#endif *pPid = cp->pid; @@ -957,284 +961,6 @@ return pid; } -/* Emulate the select call - Wait for available input on any of the given rfds, or timeout if - a timeout is given and no input is detected - wfds and efds are not supported and must be NULL. - - For simplicity, we detect the death of child processes here and - synchronously call the SIGCHLD handler. Since it is possible for - children to be created without a corresponding pipe handle from which - to read output, we wait separately on the process handles as well as - the char_avail events for each process pipe. We only call - wait/reap_process when the process actually terminates. */ - -/* From ntterm.c */ -extern HANDLE keyboard_handle; -/* From process.c */ -extern int proc_buffered_char[]; - -int -sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds, - EMACS_TIME *timeout) -{ - SELECT_TYPE orfds; - DWORD timeout_ms, start_time; - int i, nh, nc, nr; - DWORD active; - child_process *cp, *cps[MAX_CHILDREN]; - HANDLE wait_hnd[MAXDESC + MAX_CHILDREN]; - int fdindex[MAXDESC]; /* mapping from wait handles back to descriptors */ - - timeout_ms = timeout ? (timeout->tv_sec * 1000 + timeout->tv_usec / 1000) : INFINITE; - - /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */ - if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) - { - Sleep (timeout_ms); - return 0; - } - - /* Otherwise, we only handle rfds, so fail otherwise. */ - if (rfds == NULL || wfds != NULL || efds != NULL) - { - errno = EINVAL; - return -1; - } - - orfds = *rfds; - FD_ZERO (rfds); - nr = 0; - - /* Build a list of pipe handles to wait on. */ - nh = 0; - for (i = 0; i < nfds; i++) - if (FD_ISSET (i, &orfds)) - { - if (i == 0) - { -#if 0 -/* Sync with FSF Emacs 19.34.6 note: ifdef'ed out in XEmacs */ - if (keyboard_handle) - { - /* Handle stdin specially */ - wait_hnd[nh] = keyboard_handle; - fdindex[nh] = i; - nh++; - } -#endif - - /* Check for any emacs-generated input in the queue since - it won't be detected in the wait */ - if (detect_input_pending ()) - { - FD_SET (i, rfds); - return 1; - } - } - else - { - /* Child process and socket input */ - cp = fd_info[i].cp; - if (cp) - { - int current_status = cp->status; - - if (current_status == STATUS_READ_ACKNOWLEDGED) - { - /* Tell reader thread which file handle to use. */ - cp->fd = i; - /* Wake up the reader thread for this process */ - cp->status = STATUS_READ_READY; - if (!SetEvent (cp->char_consumed)) - DebPrint (("nt_select.SetEvent failed with " - "%lu for fd %ld\n", GetLastError (), i)); - } - -#ifdef CHECK_INTERLOCK - /* slightly crude cross-checking of interlock between threads */ - - current_status = cp->status; - if (WaitForSingleObject (cp->char_avail, 0) == WAIT_OBJECT_0) - { - /* char_avail has been signalled, so status (which may - have changed) should indicate read has completed - but has not been acknowledged. */ - current_status = cp->status; - if (current_status != STATUS_READ_SUCCEEDED && - current_status != STATUS_READ_FAILED) - DebPrint (("char_avail set, but read not completed: status %d\n", - current_status)); - } - else - { - /* char_avail has not been signalled, so status should - indicate that read is in progress; small possibility - that read has completed but event wasn't yet signalled - when we tested it (because a context switch occurred - or if running on separate CPUs). */ - if (current_status != STATUS_READ_READY && - current_status != STATUS_READ_IN_PROGRESS && - current_status != STATUS_READ_SUCCEEDED && - current_status != STATUS_READ_FAILED) - DebPrint (("char_avail reset, but read status is bad: %d\n", - current_status)); - } -#endif - wait_hnd[nh] = cp->char_avail; - fdindex[nh] = i; - if (!wait_hnd[nh]) abort (); - nh++; -#ifdef FULL_DEBUG - DebPrint (("select waiting on child %d fd %d\n", - cp-child_procs, i)); -#endif - } - else - { - /* Unable to find something to wait on for this fd, skip */ - - /* Note that this is not a fatal error, and can in fact - happen in unusual circumstances. Specifically, if - sys_spawnve fails, eg. because the program doesn't - exist, and debug-on-error is t so Fsignal invokes a - nested input loop, then the process output pipe is - still included in input_wait_mask with no child_proc - associated with it. (It is removed when the debugger - exits the nested input loop and the error is thrown.) */ - - DebPrint (("sys_select: fd %ld is invalid! ignoring\n", i)); - } - } - } - -count_children: - /* Add handles of child processes. */ - nc = 0; - for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--) - /* Some child_procs might be sockets; ignore them. Also some - children may have died already, but we haven't finished reading - the process output; ignore them too. */ - if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess - && (cp->fd < 0 - || (fd_info[cp->fd].flags & FILE_SEND_SIGCHLD) == 0 - || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) - ) - { - wait_hnd[nh + nc] = cp->procinfo.hProcess; - cps[nc] = cp; - nc++; - } - - /* Nothing to look for, so we didn't find anything */ - if (nh + nc == 0) - { - if (timeout) - Sleep (timeout_ms); - return 0; - } - - /* Wait for input or child death to be signalled. */ - start_time = GetTickCount (); - active = WaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms); - - if (active == WAIT_FAILED) - { - DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n", - nh + nc, timeout_ms, GetLastError ())); - /* don't return EBADF - this causes wait_reading_process_input to - abort; WAIT_FAILED is returned when single-stepping under - Windows 95 after switching thread focus in debugger, and - possibly at other times. */ - errno = EINTR; - return -1; - } - else if (active == WAIT_TIMEOUT) - { - return 0; - } - else if (active >= WAIT_OBJECT_0 && - active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS) - { - active -= WAIT_OBJECT_0; - } - else if (active >= WAIT_ABANDONED_0 && - active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS) - { - active -= WAIT_ABANDONED_0; - } - else - abort (); - - /* Loop over all handles after active (now officially documented as - being the first signalled handle in the array). We do this to - ensure fairness, so that all channels with data available will be - processed - otherwise higher numbered channels could be starved. */ - do - { - if (active >= nh) - { - cp = cps[active - nh]; - - /* We cannot always signal SIGCHLD immediately; if we have not - finished reading the process output, we must delay sending - SIGCHLD until we do. */ - - if (cp->fd >= 0 && (fd_info[cp->fd].flags & FILE_AT_EOF) == 0) - fd_info[cp->fd].flags |= FILE_SEND_SIGCHLD; - /* SIG_DFL for SIGCHLD is ignore */ - else - { -#ifdef FULL_DEBUG - DebPrint (("select is raising SIGCHLD handler for pid %d\n", - cp->pid)); -#endif - dead_child = cp; - /* msw_raise (SIGCHLD); -kkm: I will erase this file - slowly, line by line, character by character, - I will press undo often, to prolong this. - Even such a revenge will not be enough for it!!! */ - dead_child = NULL; - } - } - else if (fdindex[active] == 0) - { - /* Keyboard input available */ - FD_SET (0, rfds); - nr++; - } - else - { - /* must be a socket or pipe - read ahead should have - completed, either succeeding or failing. */ - FD_SET (fdindex[active], rfds); - nr++; - } - - /* Even though wait_reading_process_output only reads from at most - one channel, we must process all channels here so that we reap - all children that have died. */ - while (++active < nh + nc) - if (WaitForSingleObject (wait_hnd[active], 0) == WAIT_OBJECT_0) - break; - } while (active < nh + nc); - - /* If no input has arrived and timeout hasn't expired, wait again. */ - if (nr == 0) - { - DWORD elapsed = GetTickCount () - start_time; - - if (timeout_ms > elapsed) /* INFINITE is MAX_UINT */ - { - if (timeout_ms != INFINITE) - timeout_ms -= elapsed; - goto count_children; - } - } - - return nr; -} - /* Substitute for certain kill () operations */ static BOOL CALLBACK @@ -1493,75 +1219,6 @@ { process_dir = dir; } - -#ifdef HAVE_SOCKETS - -/* To avoid problems with winsock implementations that work over dial-up - connections causing or requiring a connection to exist while Emacs is - running, Emacs no longer automatically loads winsock on startup if it - is present. Instead, it will be loaded when open-network-stream is - first called. - - To allow full control over when winsock is loaded, we provide these - two functions to dynamically load and unload winsock. This allows - dial-up users to only be connected when they actually need to use - socket services. */ - -/* From nt.c */ -extern HANDLE winsock_lib; -extern BOOL term_winsock (void); -extern BOOL init_winsock (int load_now); - -extern Lisp_Object Vsystem_name; - -DEFUN ("win32-has-winsock", Fwin32_has_winsock, 0, 1, "", /* -Test for presence of the Windows socket library `winsock'. -Returns non-nil if winsock support is present, nil otherwise. - -If the optional argument LOAD-NOW is non-nil, the winsock library is -also loaded immediately if not already loaded. If winsock is loaded, -the winsock local hostname is returned (since this may be different from -the value of `system-name' and should supplant it), otherwise t is -returned to indicate winsock support is present. -*/ - (load_now)) -{ - int have_winsock; - - have_winsock = init_winsock (!NILP (load_now)); - if (have_winsock) - { - if (winsock_lib != NULL) - { - /* Return new value for system-name. The best way to do this - is to call init_system_name, saving and restoring the - original value to avoid side-effects. */ - Lisp_Object orig_hostname = Vsystem_name; - Lisp_Object hostname; - - init_system_name (); - hostname = Vsystem_name; - Vsystem_name = orig_hostname; - return hostname; - } - return Qt; - } - return Qnil; -} - -DEFUN ("win32-unload-winsock", Fwin32_unload_winsock, 0, 0, "", /* -Unload the Windows socket library `winsock' if loaded. -This is provided to allow dial-up socket connections to be disconnected -when no longer needed. Returns nil without unloading winsock if any -socket connections still exist. -*/ - ()) -{ - return term_winsock () ? Qt : Qnil; -} - -#endif /* HAVE_SOCKETS */ - /* Some miscellaneous functions that are Windows specific, but not GUI specific (ie. are applicable in terminal or batch mode as well). */ @@ -1818,10 +1475,6 @@ Qhigh = intern ("high"); Qlow = intern ("low"); -#ifdef HAVE_SOCKETS - DEFSUBR (Fwin32_has_winsock); - DEFSUBR (Fwin32_unload_winsock); -#endif DEFSUBR (Fwin32_short_file_name); DEFSUBR (Fwin32_long_file_name); DEFSUBR (Fwin32_set_process_priority); @@ -1862,7 +1515,7 @@ */ ); Vwin32_start_process_share_console = Qnil; - DEFVAR_INT ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /* + DEFVAR_LISP ("win32-pipe-read-delay", &Vwin32_pipe_read_delay /* Forced delay before reading subprocess output. This is done to improve the buffering of subprocess output, by avoiding the inefficiency of frequently reading small amounts of data. @@ -1872,7 +1525,7 @@ of time slices to wait (effectively boosting the priority of the child process temporarily). A value of zero disables waiting entirely. */ ); - Vwin32_pipe_read_delay = 50; + Vwin32_pipe_read_delay = make_int (50); #if 0 DEFVAR_LISP ("win32-generate-fake-inodes", &Vwin32_generate_fake_inodes /*