View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000570 | Perl for OS/2 | Bug | public | 2013-04-21 12:37 | 2020-09-21 09:08 |
Reporter | komh | Assigned To | psmedley | ||
Priority | high | Severity | major | Reproducibility | always |
Status | closed | Resolution | reopened | ||
Summary | 0000570: perl 5.10.0 and coreutils | ||||
Description | Hi/2. Trying to autoreconf coreutils always fails. I tested with coreutils 8.8, 8.21 and git repo. I've used autoconf 2.69 and automake 1.13.1. But any other version of autotools failed, too. | ||||
Steps To Reproduce | Call following scripts in coreutils directory. ----- ar.cmd extproc sh export COMSPEC=/bin/sh autoreconf -fvi $* ----- Just call ar.cmd Then you can see the logs I attach. | ||||
Tags | No tags attached. | ||||
Attached Files | Pass-a-very-long-command-line-via-a-response-file.patch (6,742 bytes)
diff --git a/os2/os2.c b/os2/os2.c index abbd337..cfffdfe 100644 --- a/os2/os2.c +++ b/os2/os2.c @@ -900,6 +900,182 @@ getpriority(int which /* ignored */, int pid) +/* OS/2 can process a command line up to 32K. But set the maximum length + * to 16K for the safety */ +#define MAX_CMD_LINE_LEN 16384 + +struct rsp_temp { + int pid; + char *name; + struct rsp_temp *next; +}; + +static struct rsp_temp *rsp_temp_start = NULL; + +static void +remove_rsp_temp(int pid) +{ + struct rsp_temp *rsp_temp; + struct rsp_temp *rsp_temp_prev = NULL; + + for (rsp_temp = rsp_temp_start; rsp_temp; rsp_temp = rsp_temp->next ) { + if (pid == -1 || rsp_temp->pid == pid) { + if (rsp_temp_start == rsp_temp) + rsp_temp_start = rsp_temp->next; + else /* rsp_temp_prev must not be NULL */ + rsp_temp_prev->next = rsp_temp->next; + + remove (rsp_temp->name); + free (rsp_temp->name); + free (rsp_temp); + + if (pid != -1) + break; + } + + rsp_temp_prev = rsp_temp; + } +} + +enum rsp_spawn_t { + RSP_SPAWN, + RSP_SPAWNP, + RSP_EXEC, + RSP_EXECP +}; + +static int +rsp_spawnv(U32 rsp_spawnf, int mode, const char *name, char * const argv[]) +{ + int rc; + char *rsp_argv[3]; + char rsp_name_arg[] = "@perl-rsp-XXXXXX"; + char *rsp_name = &rsp_name_arg[1]; + int arg_len = 0; + int i; + + for (i = 0; argv[i]; i++) + arg_len += strlen(argv[i]) + 1; + + /* if a length of command line is longer than MAX_CMD_LINE_LEN, then use + * a response file. OS/2 cannot process a command line longer than 32K. + * Of course, a response file cannot be recognized by a normal OS/2 + * program, that is, neither non-EMX or non-kLIBC. But it cannot accept + * a command line longer than 32K in itself. So using a response file + * in this case, is an acceptable solution */ + if (arg_len > MAX_CMD_LINE_LEN) { + int fd; + struct temp *t; + + if ((fd = mkstemp(rsp_name)) == -1) + return -1; + + /* write all the arguments except a 0th program name */ + for (i = 1; argv[i]; i++) { + char *p = strdup(argv[i]); + char *p1 = p; + /* replace a new line with a space. + * a line in a rsp file means one argument, so a new line in an + * argument splits it into two argument. this is not expected. + * consequently, a new line character cannot be passed. pray a + * new line character should not be used as a normal character. + * ^^ + */ + while ((p1 = strchr(p1, '\n')) != NULL) + *p1++ = ' '; + write(fd, p, strlen(p)); + write(fd, "\n", 1); + free(p); + } + + close (fd); + + rsp_argv[0] = argv[0]; + rsp_argv[1] = rsp_name_arg; + rsp_argv[2] = NULL; + + argv = rsp_argv; + } + + switch (rsp_spawnf) { + case RSP_SPAWNP : + rc = spawnvp(mode, name, argv); + break; + + case RSP_EXEC : + rc = execv(name, argv); + break; + + case RSP_EXECP : + rc = execvp(name, argv); + + default : + rc = spawnv(mode, name, argv); + } + + /* a response file was generated ? */ + if (argv == rsp_argv) { + /* make a response file list to clean up later if spawned a child + * successfully */ + if (rc > 0) { + struct rsp_temp *rsp_temp_new; + + rsp_temp_new = malloc(sizeof(*rsp_temp_new)); + rsp_temp_new->pid = rc; + rsp_temp_new->name = strdup(rsp_name); + rsp_temp_new->next = rsp_temp_start; + rsp_temp_start = rsp_temp_new; + } + else if (rc < 0) /* failed, then remove immediately */ + remove(rsp_name); + /* rc == 0 : independent session. This can occur only with + * P_UNRELEATED. */ + } + + return rc; +} + +static int +rsp_spawnl(U32 rsp_spawnf, int mode, const char *name, const char *arg0, ...) +{ + int rc; + int argc, i; + const char **argv; + va_list arg_ptr; + const char *arg; + + va_start(arg_ptr, arg0); + for(i = 0, arg = arg0; arg; i++, arg = va_arg(arg_ptr, const char *)) + /* nothing*/; + va_end(arg_ptr); + + argc = i; + argv = calloc(argc + 1, sizeof(*argv)); /* 1 for NULL argument */ + + va_start(arg_ptr, arg0); + for(i = 0, arg = arg0; arg; i++, arg = va_arg(arg_ptr, const char *)) + argv[i] = strdup(arg); + va_end(arg_ptr); + + rc = rsp_spawnv(rsp_spawnf, mode, name, argv); + + for(i = 0; i < argc; i++) + free(argv[i]); + free(argv); + + return rc; +} + +#define spawnl(mode, name, arg0, ...) \ + rsp_spawnl(RSP_SPAWN, mode, name, arg0, __VA_ARGS__) + +#define spawnvp(mode, name, argv) rsp_spawnv(RSP_SPAWNP, mode, name, argv) + +#define execl(name, arg0, ...) \ + rsp_spawnl(RSP_EXEC, 0, name, arg0, __VA_ARGS__) + +#define execvp(name, argv) rsp_spawnv(RSP_EXECP, 0, name, argv) + static Signal_t spawn_sighandler(int sig) { @@ -939,6 +1115,7 @@ result(pTHX_ int flag, int pid) do { r = wait4pid(pid, &status, 0); } while (r == -1 && errno == EINTR); + remove_rsp_temp(pid); rsignal(SIGINT, ihand); rsignal(SIGQUIT, qhand); @@ -949,6 +1126,7 @@ result(pTHX_ int flag, int pid) #else ihand = rsignal(SIGINT, SIG_IGN); r = DosWaitChild(DCWA_PROCESS, DCWW_WAIT, &res, &rpid, pid); + remove_rsp_temp(pid); rsignal(SIGINT, ihand); PL_statusvalue = res.codeResult << 8 | res.codeTerminate; if (r) @@ -4919,6 +5097,10 @@ extern void _CRT_term(void); void Perl_OS2_term(void **p, int exitstatus, int flags) { + /* Remove remaining temporary response file */ + remove_rsp_temp(-1); + +#ifndef __KLIBC__ if (!emx_runtime_secondary) return; @@ -4949,6 +5131,7 @@ Perl_OS2_term(void **p, int exitstatus, int flags) if (flags & FORCE_EMX_DEINIT_CRT_TERM) _CRT_term(); /* Flush buffers, etc. */ /* Now it is a good time to call exit() in the caller's CRTL... */ +#endif } #include <emx/startup.h> diff --git a/os2/os2ish.h b/os2/os2ish.h index a2ba09f..a0f984b 100644 --- a/os2/os2ish.h +++ b/os2/os2ish.h @@ -281,6 +281,10 @@ void Perl_OS2_term(void **excH, int exitstatus, int flags); PERL_SYS_TERM1(xreg); \ } #else +#define PERL_SYS_TERM_BODY() \ + PERL_SYS_TERM1(0); \ + HINTS_REFCNT_TERM; OP_REFCNT_TERM; PERLIO_TERM; MALLOC_TERM; + #ifndef PERL_SYS_TERM_BODY # define PERL_SYS_TERM_BODY() \ HINTS_REFCNT_TERM; OP_REFCNT_TERM; PERLIO_TERM; MALLOC_TERM; 0009-Increase-MAX_CMD_LINE_LEN-to-32768.patch (760 bytes)
From edbaefa72924598099ed96edf1e2032da82be13c Mon Sep 17 00:00:00 2001 From: KO Myung-Hun <komh@chollian.net> Date: Fri, 17 May 2013 22:46:57 +0900 Subject: [PATCH 09/13] Increase MAX_CMD_LINE_LEN to 32768 Confirmed that it's safe up to 32768. --- os2/os2.c | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/os2/os2.c b/os2/os2.c index cfffdfe..bf01308 100644 --- a/os2/os2.c +++ b/os2/os2.c @@ -900,9 +900,8 @@ getpriority(int which /* ignored */, int pid) -/* OS/2 can process a command line up to 32K. But set the maximum length - * to 16K for the safety */ -#define MAX_CMD_LINE_LEN 16384 +/* OS/2 can process a command line up to 32K */ +#define MAX_CMD_LINE_LEN 32768 struct rsp_temp { int pid; -- 1.7.3.2 0012-Fix-a-potential-crash.patch (1,243 bytes)
From ff857368b326d79d375bb0c3a472e00a3283bac7 Mon Sep 17 00:00:00 2001 From: KO Myung-Hun <komh@chollian.net> Date: Sun, 19 Oct 2014 10:56:00 +0900 Subject: [PATCH 12/13] Fix a potential crash It is dangerous to use rsp_temp again after freeing it. --- os2/os2.c | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/os2/os2.c b/os2/os2.c index 1452e69..b18444f 100644 --- a/os2/os2.c +++ b/os2/os2.c @@ -916,13 +916,16 @@ remove_rsp_temp(int pid) { struct rsp_temp *rsp_temp; struct rsp_temp *rsp_temp_prev = NULL; + struct rsp_temp *rsp_temp_next = NULL; + + for (rsp_temp = rsp_temp_start; rsp_temp; rsp_temp = rsp_temp_next) { + rsp_temp_next = rsp_temp->next; - for (rsp_temp = rsp_temp_start; rsp_temp; rsp_temp = rsp_temp->next ) { if (pid == -1 || rsp_temp->pid == pid) { if (rsp_temp_start == rsp_temp) - rsp_temp_start = rsp_temp->next; + rsp_temp_start = rsp_temp_next; else /* rsp_temp_prev must not be NULL */ - rsp_temp_prev->next = rsp_temp->next; + rsp_temp_prev->next = rsp_temp_next; remove (rsp_temp->name); free (rsp_temp->name); -- 1.7.3.2 0013-Fix-leaks-of-temporary-response-files.patch (1,546 bytes)
From 383ababf2bf44fb23dc16926f8e8d9be897d09b0 Mon Sep 17 00:00:00 2001 From: KO Myung-Hun <komh@chollian.net> Date: Sun, 19 Oct 2014 10:58:03 +0900 Subject: [PATCH 13/13] Fix leaks of temporary response files If a child process was spawned with P_WAIT and it returned an error code 0, then a response file is not removed. --- os2/os2.c | 10 ++++------ 1 files changed, 4 insertions(+), 6 deletions(-) diff --git a/os2/os2.c b/os2/os2.c index b18444f..f21a4c3 100644 --- a/os2/os2.c +++ b/os2/os2.c @@ -1018,8 +1018,8 @@ rsp_spawnv(U32 rsp_spawnf, int mode, const char *name, char * const argv[]) /* a response file was generated ? */ if (argv == rsp_argv) { /* make a response file list to clean up later if spawned a child - * successfully */ - if (rc > 0) { + * successfully except P_WAIT */ + if (rc >= 0 && mode != P_WAIT) { struct rsp_temp *rsp_temp_new; rsp_temp_new = malloc(sizeof(*rsp_temp_new)); @@ -1028,10 +1028,8 @@ rsp_spawnv(U32 rsp_spawnf, int mode, const char *name, char * const argv[]) rsp_temp_new->next = rsp_temp_start; rsp_temp_start = rsp_temp_new; } - else if (rc < 0) /* failed, then remove immediately */ - remove(rsp_name); - /* rc == 0 : independent session. This can occur only with - * P_UNRELEATED. */ + else /* failed or P_WAIT ? */ + remove(rsp_name); /* remove immediately */ } return rc; -- 1.7.3.2 | ||||
|
This is a very long command line problem. I attach a patch. |
|
thanks, will apply before I next build perl |
|
It's safe to increase MAX_CMD_LINE_LEN to 32768. ^^ |
|
Patch will be included in 5.16.3 |
|
Some fixes are there. |
|
Please, modify again. ^^ mode != P_WAIT of 0013-Fix-leaks-of-temporary-response-files.patch to ( mode & 0xFF ) != P_WAIT |
|
I'll check to see if I included these patches - I don't recall any more. FYI I released a build of perl 5.32.0 on the weekend |
|
9 & 12 are in the build of perl 5.32.0 I posted to os2world on the weekend. I've now added 13, but I don't understand the patch in 2896.... |
|
Long time no see, Paul. Instead, you can check more patches from here: https://github.com/komh/perl-os2/commits/5.16.0-os2 And do you have any plans to upload this project to github ? If possible, it would be better that all the other projects do. |
|
Hi KO - the goal is to get the source uploaded into the Perl repository... |
|
Ok. Thanks! |
Date Modified | Username | Field | Change |
---|---|---|---|
2013-04-21 12:37 | komh | New Issue | |
2013-04-21 12:37 | komh | File Added: autoreconf.log | |
2013-04-29 13:32 | komh | Note Added: 0002439 | |
2013-04-29 13:33 | komh | File Added: Pass-a-very-long-command-line-via-a-response-file.patch | |
2013-04-30 09:19 | psmedley | Note Added: 0002442 | |
2013-05-17 13:49 | komh | Note Added: 0002446 | |
2013-05-18 09:34 | psmedley | Note Added: 0002449 | |
2013-05-18 09:34 | psmedley | Status | new => resolved |
2013-05-18 09:34 | psmedley | Resolution | open => fixed |
2013-05-18 09:34 | psmedley | Assigned To | => psmedley |
2014-10-19 02:28 | komh | Note Added: 0002894 | |
2014-10-19 02:28 | komh | Status | resolved => feedback |
2014-10-19 02:28 | komh | Resolution | fixed => reopened |
2014-10-19 02:28 | komh | File Added: 0009-Increase-MAX_CMD_LINE_LEN-to-32768.patch | |
2014-10-19 02:28 | komh | File Added: 0012-Fix-a-potential-crash.patch | |
2014-10-19 02:28 | komh | File Added: 0013-Fix-leaks-of-temporary-response-files.patch | |
2014-10-21 15:47 | komh | Note Added: 0002896 | |
2014-10-21 15:47 | komh | Status | feedback => assigned |
2020-08-31 00:06 | psmedley | Note Added: 0003523 | |
2020-08-31 09:49 | psmedley | Note Added: 0003525 | |
2020-09-18 12:01 | komh | Note Added: 0003541 | |
2020-09-19 21:23 | psmedley | Note Added: 0003542 | |
2020-09-20 03:31 | komh | Note Added: 0003543 | |
2020-09-21 09:08 | psmedley | Status | assigned => closed |