Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Message-ID: <3B509AA3.3F3AF7FC@nc.rr.com> Date: Sat, 14 Jul 2001 15:16:51 -0400 From: Greg Smith X-Mailer: Mozilla 4.77 [en] (Windows NT 5.0; U) X-Accept-Language: en MIME-Version: 1.0 To: cygwin AT cygwin DOT com CC: Fish Subject: execve() fails in a thread under 98/ME Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit One of our developers has found a subtle bug due to the fact that PAGE_GUARD is not valid for VirtualAlloc() under Windows 98/ME. A testcase is provided below. I don't have access to 98/ME so I haven't created the failure myself, but I am assured it happens. I do know the testcase doesn't fail under w2k. Below are the developers comments. Thanks, Greg It's in Cygwin's code, but in all fairness it's probably not their fault. I suspect this particular part of Cygwin was more than likely coded before Microsoft corrected their documentation oversight. You see, if you look at cygwin's "alloc_stack_hard_way" function (in source module "dcrt0.cc"), you'll notice them doing: if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT, PAGE_EXECUTE_READWRITE|PAGE_GUARD)) api_fatal ("fork: couldn't allocate new stack guard page %p, %E", m.BaseAddress); The only problem is, the "PAGE_GUARD" flag is not supported on Win9x/ME platforms! This is NOT mentioned anywhere in the *original* SDK documentation, but apparently they've finally gotten around to correcting this oversight in their latest version of the docs, because it now mentions it quite plainly in the description of the VirtualAlloc function: ------------------------------- [...] PAGE_GUARD Windows NT/2000 or later: Pages in the region become guard pages. Any attempt to read from or write to a guard page causes the system to raise a STATUS_GUARD_PAGE exception and turn off the guard page status. Guard pages thus act as a one-shot access alarm. PAGE_GUARD is a page protection modifier. An application uses it with one of the other page protection modifiers, with one exception: it cannot be used with PAGE_NOACCESS. When an access attempt leads the system to turn off guard page status, the underlying page protection takes over. If a guard page exception occurs during a system service, the service typically returns a failure status indicator. Windows 95/98/Me: To simulate this behavior, use PAGE_NOACCESS. PAGE_NOACCESS Disables all access to the committed region of pages. An attempt to read from, write to, or execute in the committed region results in an access violation exception, called a general protection (GP) fault. [...] ------------------------------- So Greg, could you mention this to them please? They need to either add some Win9x specific code to dcrt0.cc or else change it to use PAGE_NOACCESS for *all* platforms (in which case they'll have to catch the access violation exception rather than the STATUS_GUARD_PAGE exception). Test case: $ cat shtest.c #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef u_int8_t BYTE; typedef pthread_attr_t ATTR; typedef pthread_t TID; ATTR detattr; FILE* msgpiper; FILE* msgpipew; int herc_system (char *command) { extern char **environ; int pid, status; if (command == 0) return 1; pid = fork(); if (pid == -1) return -1; if (pid == 0) { char *argv[4]; dup2(msgpiper, STDIN_FILENO); dup2(fileno(msgpipew), STDOUT_FILENO); dup2(fileno(msgpipew), STDERR_FILENO); argv[0] = "sh"; argv[1] = "-c"; argv[2] = command; argv[3] = 0; execve("/bin/sh", argv, environ); exit(127); } do { if (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) return -1; } else return status; } while(1); } static void *panel_command (void *cmdline) { herc_system("ls -al"); return NULL; } #define CMD_SIZE 32767 #define initialize_detach_attr(pat) \ pthread_attr_init((pat)); \ pthread_attr_setdetachstate((pat),PTHREAD_CREATE_DETACHED) typedef void*THREAD_FUNC(void*); #define create_thread(ptid,pat,fn,arg) \ pthread_create(ptid,pat,(THREAD_FUNC*)&(fn),arg) int main (int argc, char *argv[]) { TID cmdtid; BYTE cmdline[CMD_SIZE+1]; msgpiper = stdin; msgpipew = stdout; initialize_detach_attr (&detattr); // panel_command("xxx"); create_thread (&cmdtid, &detattr, panel_command, cmdline); sleep(3); return 0; } -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/