FAQ
In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/6de23f80b0db931a33c28fa9eea3c74f533d772b?hp=e46aa1ddb7d58d270bbc45cef016b0577cfdecaa>

- Log -----------------------------------------------------------------
commit 6de23f80b0db931a33c28fa9eea3c74f533d772b
Author: Andy Broad <andy@broad.ology.org.uk>
Date: Fri Mar 11 20:20:31 2016 -0500

     amigaos4: better popen() + pclose() implementation

     popen(): handle better the case where the popened external
     might exit before the child process manages to start.

     pclose(): protect with a semaphore.
-----------------------------------------------------------------------

Summary of changes:
  amigaos4/amigaio.c | 15 +++++++--
  amigaos4/amigaos.c | 91 ++++++++++++++++++++++++++++++++++++++++--------------
  amigaos4/amigaos.h | 2 ++
  util.c | 5 +--
  4 files changed, 82 insertions(+), 31 deletions(-)

diff --git a/amigaos4/amigaio.c b/amigaos4/amigaio.c
index a5eb112..40e9835 100644
--- a/amigaos4/amigaio.c
+++ b/amigaos4/amigaio.c
@@ -18,6 +18,7 @@
  #include <exec/exectags.h>
  #include <proto/exec.h>
  #include <proto/dos.h>
+#include <proto/utility.h>
  #include <dos/dos.h>

  void amigaos_stdio_get(pTHX_ StdioStore *store)
@@ -66,10 +67,18 @@ PerlIO *Perl_my_popen(pTHX_ const char *cmd, const char *mode)
   */
   // FILE *f=amigaos_popen(cmd,mode);
   // fprintf(stderr,"popen returned %d\n",f);
- return PerlIO_importFILE(amigaos_popen(cmd, mode), 0);
+ return PerlIO_importFILE(amigaos_popen(cmd, mode), mode);
   // return PerlIO_importFILE(f, 0);
  }

+I32 Perl_my_pclose(pTHX_ PerlIO *ptr)
+{
+ FILE * const f = PerlIO_findFILE(ptr);
+ const I32 result = amigaos_pclose(f);
+ PerlIO_releaseFILE(ptr,f);
+ return result;
+}
+
  #ifdef USE_ITHREADS

  /* An arbitrary number to start with, should work out what the real max should
@@ -747,7 +756,7 @@ int myexecve(bool isperlthread,
        (contains_whitespace(*cur) ? (2 + no_of_escapes(*cur)) : 0);
   }
   /* Check if it's a script file */
-
+ IExec->DebugPrintF("%s %ld %08lx %c %c\n",__FILE__,__LINE__,filename,filename[0],filename[1]);
   fh = fopen(filename, "r");
   if (fh)
   {
@@ -839,7 +848,7 @@ int myexecve(bool isperlthread,

      if (esc > 0)
      {
- char *buff = IExec->AllocVec(
+ char *buff = (char *)IExec->AllocVec(
                        strlen(*cur) + 4 + esc,
                        MEMF_ANY | MEMF_CLEAR);
       char *p = *cur;
diff --git a/amigaos4/amigaos.c b/amigaos4/amigaos.c
index 44860c9..67b4c06 100644
--- a/amigaos4/amigaos.c
+++ b/amigaos4/amigaos.c
@@ -241,10 +241,13 @@ char *convert_path_u2a(const char *filename)
  }

  static struct SignalSemaphore environ_sema;
+static struct SignalSemaphore popen_sema;
+

  void amigaos4_init_environ_sema()
  {
   IExec->InitSemaphore(&environ_sema);
+ IExec->InitSemaphore(&popen_sema);
  }

  void amigaos4_obtain_environ()
@@ -310,6 +313,7 @@ struct command_data
   struct Task *parent;
  };

+
  int myexecvp(bool isperlthread, const char *filename, char *argv[])
  {
   // adebug("%s %ld
@@ -518,16 +522,23 @@ void ___freeenviron()

  /* reimplementation of popen, clib2's doesn't do all we want */

+struct popen_data
+{
+ struct Task *parent;
+ STRPTR command;
+};
+
+static int popen_result = 0;
+
  int popen_child()
  {
   struct Task *thisTask = IExec->FindTask(0);
-
- char *command = (char *)thisTask->tc_UserData;
+ struct popen_data *pd = (struct popen_data *)thisTask->tc_UserData;
   const char *argv[4];

   argv[0] = "sh";
   argv[1] = "-c";
- argv[2] = command ? command : NULL;
+ argv[2] = pd->command ? pd->command : NULL;
   argv[3] = NULL;

   // adebug("%s %ld %s\n",__FUNCTION__,__LINE__,command?command:"NULL");
@@ -535,11 +546,16 @@ int popen_child()
   /* We need to give this to sh via execvp, execvp expects filename,
    * argv[]
    */
+ IExec->ObtainSemaphore(&popen_sema);
+
+ IExec->Signal(pd->parent,SIGBREAKF_CTRL_F);

- myexecvp(FALSE, argv[0], (char **)argv);
- if (command)
- IExec->FreeVec(command);
+ popen_result = myexecvp(FALSE, argv[0], (char **)argv);
+ if (pd->command)
+ IExec->FreeVec(pd->command);
+ IExec->FreeVec(pd);

+ IExec->ReleaseSemaphore(&popen_sema);
   IExec->Forbid();
   return 0;
  }
@@ -551,11 +567,11 @@ FILE *amigaos_popen(const char *cmd, const char *mode)
   char pipe_name[50];
   char unix_pipe[50];
   char ami_pipe[50];
- char *cmd_copy;
   BPTR input = 0;
   BPTR output = 0;
   struct Process *proc = NULL;
   struct Task *thisTask = IExec->FindTask(0);
+ struct popen_data * pd = NULL;

   /* First we need to check the mode
    * We can only have unidirectional pipes
@@ -585,15 +601,15 @@ FILE *amigaos_popen(const char *cmd, const char *mode)
   sprintf(unix_pipe, "/PIPE/%s", pipe_name);
   sprintf(ami_pipe, "PIPE:%s", pipe_name);

- /* Now we open the AmigaOs filehandles that we will pass to our
- * subprocess
+ /* Now we open the AmigaOs Filehandles That we wil pass to our
+ * Sub process
    */

   if (mode[0] == 'r')
   {
    /* A read mode pipe: Output from pipe input from Output() or NIL:*/
    /* First attempt to DUP Output() */
- input = IDOS->DupFileHandle(IDOS->Output());
+ input = IDOS->DupFileHandle(IDOS->Input());
    if(input == 0)
    {
     input = IDOS->Open("NIL:", MODE_READWRITE);
@@ -613,7 +629,7 @@ FILE *amigaos_popen(const char *cmd, const char *mode)
    input = IDOS->Open(ami_pipe, MODE_OLDFILE);
    if (input != 0)
    {
- output = IDOS->DupFileHandle(IDOS->Input());
+ output = IDOS->DupFileHandle(IDOS->Output());
     if(output == 0)
     {
      output = IDOS->Open("NIL:", MODE_READWRITE);
@@ -643,29 +659,44 @@ FILE *amigaos_popen(const char *cmd, const char *mode)
    * no time in overwriting it! The subprocess will free the copy.
    */

- if ((cmd_copy = mystrdup(cmd)))
+ if((pd = (struct popen_data*)IExec->AllocVecTags(sizeof(struct popen_data),AVT_Type,MEMF_SHARED,TAG_DONE)))
   {
- // adebug("%s %ld
- // %s\n",__FUNCTION__,__LINE__,cmd_copy?cmd_copy:"NULL");
- proc = IDOS->CreateNewProcTags(
- NP_Entry, popen_child, NP_Child, TRUE, NP_StackSize,
- ((struct Process *)thisTask)->pr_StackSize, NP_Input, input,
- NP_Output, output, NP_Error, IDOS->ErrorOutput(),
- NP_CloseError, FALSE, NP_Cli, TRUE, NP_Name,
- "Perl: popen process", NP_UserData, (int)cmd_copy,
- TAG_DONE);
+ pd->parent = thisTask;
+ if ((pd->command = mystrdup(cmd)))
+ {
+ // adebug("%s %ld
+ // %s\n",__FUNCTION__,__LINE__,cmd_copy?cmd_copy:"NULL");
+ proc = IDOS->CreateNewProcTags(
+ NP_Entry, popen_child, NP_Child, TRUE, NP_StackSize,
+ ((struct Process *)thisTask)->pr_StackSize, NP_Input, input,
+ NP_Output, output, NP_Error, IDOS->ErrorOutput(),
+ NP_CloseError, FALSE, NP_Cli, TRUE, NP_Name,
+ "Perl: popen process", NP_UserData, (int)pd,
+ TAG_DONE);
+ }
+ }
+ if(proc)
+ {
+ /* wait for the child be setup right */
+ IExec->Wait(SIGBREAKF_CTRL_F);
   }
   if (!proc)
   {
    /* New Process Failed to start
     * Close and bail out
     */
+ if(pd)
+ {
+ if(pd->command)
+ {
+ IExec->FreeVec(pd->command);
+ }
+ IExec->FreeVec(pd);
+ }
    if (input)
     IDOS->Close(input);
    if (output)
     IDOS->Close(output);
- if (cmd_copy)
- IExec->FreeVec(cmd_copy);
    if(result)
    {
     fclose(result);
@@ -680,7 +711,19 @@ FILE *amigaos_popen(const char *cmd, const char *mode)
   return result;
  }

-/* Workaround for clib2 fstat */
+int amigaos_pclose(FILE *f)
+{
+ int result = -1;
+ /* close the file before obtaining the semaphore else we might end up
+ hanging waiting for the child to read the last bit from the pipe */
+ fclose(f);
+ IExec->ObtainSemaphore(&popen_sema);
+ result = popen_result;
+ IExec->ReleaseSemaphore(&popen_sema);
+ return result;
+}
+
+/* Work arround for clib2 fstat */
  #ifndef S_IFCHR
  #define S_IFCHR 0x0020000
  #endif
diff --git a/amigaos4/amigaos.h b/amigaos4/amigaos.h
index 0faff80..4640bfa 100644
--- a/amigaos4/amigaos.h
+++ b/amigaos4/amigaos.h
@@ -33,6 +33,8 @@ int myexecl(bool isperlthread, const char *path, ...);
  int pipe(int filedes[2]);

  FILE *amigaos_popen(const char *cmd, const char *mode);
+int amigaos_pclose(FILE *f);
+
  void amigaos4_obtain_environ();
  void amigaos4_release_environ();

diff --git a/util.c b/util.c
index c18555c..98e6be5 100644
--- a/util.c
+++ b/util.c
@@ -3175,10 +3175,7 @@ S_pidgone(pTHX_ Pid_t pid, int status)
  }
  #endif

-#if defined(OS2) || defined(__amigaos4__)
-# if defined(__amigaos4__) && defined(pclose)
-# undef pclose
-# endif
+#if defined(OS2)
  int pclose();
  #ifdef HAS_FORK
  int /* Cannot prototype with I32

--
Perl5 Master Repository

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 1 of 1 | next ›
Discussion Overview
groupperl5-changes @
categoriesperl
postedMar 12, '16 at 1:50a
activeMar 12, '16 at 1:50a
posts1
users1
websiteperl.org

1 user in discussion

Jarkko Hietaniemi: 1 post

People

Translate

site design / logo © 2017 Grokbase