View Issue Details

IDProjectCategoryView StatusLast Update
0000570Perl for OS/2Bugpublic2020-09-21 09:08
Reporterkomh Assigned Topsmedley  
PriorityhighSeveritymajorReproducibilityalways
Status closedResolutionreopened 
Summary0000570: perl 5.10.0 and coreutils
DescriptionHi/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 ReproduceCall 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.
TagsNo tags attached.
Attached Files
autoreconf.log (39,423 bytes)
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

Activities

komh

2013-04-29 13:32

reporter   ~0002439

This is a very long command line problem.

I attach a patch.

psmedley

2013-04-30 09:19

administrator   ~0002442

thanks, will apply before I next build perl

komh

2013-05-17 13:49

reporter   ~0002446

It's safe to increase MAX_CMD_LINE_LEN to 32768. ^^

psmedley

2013-05-18 09:34

administrator   ~0002449

Patch will be included in 5.16.3

komh

2014-10-19 02:28

reporter   ~0002894

Some fixes are there.

komh

2014-10-21 15:47

reporter   ~0002896

Please, modify again. ^^

  mode != P_WAIT of 0013-Fix-leaks-of-temporary-response-files.patch

to

  ( mode & 0xFF ) != P_WAIT

psmedley

2020-08-31 00:06

administrator   ~0003523

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

psmedley

2020-08-31 09:49

administrator   ~0003525

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....

komh

2020-09-18 12:01

reporter   ~0003541

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.

psmedley

2020-09-19 21:23

administrator   ~0003542

Hi KO - the goal is to get the source uploaded into the Perl repository...

komh

2020-09-20 03:31

reporter   ~0003543

Ok. Thanks!

Issue History

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