X-Recipient: archive-cygwin AT delorie DOT com X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Date: Fri, 9 Mar 2012 02:14:02 +0100 From: Enrico Forestieri To: cygwin AT cygwin DOT com Subject: Forking a program in a thread Message-ID: <20120309011402.GA4704@GIOVE> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="mYCpIKhGyMATD0i+" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com --mYCpIKhGyMATD0i+ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I would like to point out a regression, seemingly introduced in 1.7.10. If a program is exec'ed after forking in a thread and the program is a native Windows program, it (seemingly) fails to start. Please, find attached a test case. You can try it with gvim, for example. There's no problem with the cygwin version of gvim: $ ./fork_in_thread /usr/bin/gvim but trying to start the native windows version: $ ./fork_in_thread "/cygdrive/c/Program Files/Vim/vim73/gvim" fails, in the sense that nothing happens and no error is reported. A workaround here is using env. Indeed, the following works: $ ./fork_in_thread env "/cygdrive/c/Program Files/Vim/vim73/gvim" However, what puzzles me is the fact that a wrapper (like the one below) starting gvim by using system() and compiled with i686-pc-mingw32-gcc works, too! All the previous examples were working in 1.7.9. ----- wrapper.c ----- #include int main(void) { system("\"C:/Program Files/Vim/vim73/gvim\""); return 0; } --------------------- -- Enrico --mYCpIKhGyMATD0i+ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="fork_in_thread.c" /* * Forks a program in a thread. */ #include #include #include #include #include void *start(void *arg) { int pid, status; char **av = (char **)arg; printf("Forking in a thread to start %s\n", av[0]); pid = fork(); if (pid == -1) { perror("fork"); exit(1); } if (pid == 0) { execvp(av[0], av); perror("execvp"); exit(1); } printf("Waiting in thread for %s to finish\n", av[0]); if (wait(&status) == -1) { perror("wait"); exit(1); } if (WIFEXITED(status) && WEXITSTATUS(status)) fprintf(stderr, "%s returned nonzero status %d", av[0], WEXITSTATUS(status)); pthread_exit(NULL); } int main (int argc, char *argv[]) { pthread_t thread; int i, rc; char **av; if (argc < 2) { printf("Usage: %s [ ...]\n", argv[0]); exit(0); } /* Build the argument vector for the child */ av = malloc(argc * sizeof(char *)); if (!av) { fprintf(stderr, "%s: no memory\n", argv[0]); exit(1); } for (i = 0; i < argc - 1; ++i) { av[i] = strdup(argv[i + 1]); if (!av[i]) { fprintf(stderr, "%s: no memory\n", argv[0]); exit(1); } } av[argc - 1] = NULL; printf("Main: creating thread for starting %s\n", argv[1]); rc = pthread_create(&thread, NULL, start, (void *)av); if (rc) { fprintf(stderr, "Error: return code from pthread_create() is %d\n", rc); exit(1); } return 0; } --mYCpIKhGyMATD0i+ Content-Type: text/plain; charset=us-ascii -- Problem reports: http://cygwin.com/problems.html FAQ: http://cygwin.com/faq/ Documentation: http://cygwin.com/docs.html Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple --mYCpIKhGyMATD0i+--