Просмотр исходного кода

Signal safety
Author: jgg
Date: 1999-03-16 00:43:55 GMT
Signal safety

Arch Librarian лет назад: 22
Родитель
Сommit
b0db36b1ac
5 измененных файлов с 119 добавлено и 27 удалено
  1. 21 2
      apt-pkg/acquire-worker.cc
  2. 8 2
      apt-pkg/acquire.cc
  3. 73 19
      apt-pkg/contrib/fileutl.cc
  4. 4 1
      apt-pkg/contrib/strutl.cc
  5. 13 3
      cmdline/acqprogress.cc

+ 21 - 2
apt-pkg/acquire-worker.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: acquire-worker.cc,v 1.19 1999/01/30 08:08:54 jgg Exp $
+// $Id: acquire-worker.cc,v 1.20 1999/03/16 00:43:55 jgg Exp $
 /* ######################################################################
 
    Acquire Worker 
@@ -24,9 +24,11 @@
 
 #include <sys/stat.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <signal.h>
 #include <wait.h>
 #include <stdio.h>
+#include <errno.h>
 									/*}}}*/
 
 // Worker::Worker - Constructor for Queue startup			/*{{{*/
@@ -130,6 +132,17 @@ bool pkgAcquire::Worker::Start()
       SetCloseExec(STDOUT_FILENO,false);
       SetCloseExec(STDIN_FILENO,false);      
       SetCloseExec(STDERR_FILENO,false);
+
+      signal(SIGPIPE,SIG_DFL);
+      signal(SIGQUIT,SIG_DFL);
+      signal(SIGINT,SIG_DFL);
+      signal(SIGWINCH,SIG_DFL);
+      signal(SIGCONT,SIG_DFL);
+      signal(SIGTSTP,SIG_DFL);
+      
+      // Close all of our FDs - just in case
+      for (int K = 3; K != 40; K++)
+	 fcntl(K,F_SETFD,FD_CLOEXEC);
       
       const char *Args[2];
       Args[0] = Method.c_str();
@@ -433,7 +446,13 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item)
 /* */
 bool pkgAcquire::Worker::OutFdReady()
 {
-   int Res = write(OutFd,OutQueue.begin(),OutQueue.length());
+   int Res;
+   do
+   {
+      Res = write(OutFd,OutQueue.begin(),OutQueue.length());
+   }
+   while (Res < 0 && errno == EINTR);
+   
    if (Res <= 0)
       return MethodFailure();
 

+ 8 - 2
apt-pkg/acquire.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: acquire.cc,v 1.28 1999/03/15 08:10:39 jgg Exp $
+// $Id: acquire.cc,v 1.29 1999/03/16 00:43:55 jgg Exp $
 /* ######################################################################
 
    Acquire - File Acquiration
@@ -297,7 +297,13 @@ bool pkgAcquire::Run()
       FD_ZERO(&WFds);
       SetFds(Highest,&RFds,&WFds);
       
-      int Res = select(Highest+1,&RFds,&WFds,0,&tv);
+      int Res;
+      do
+      {
+	 Res = select(Highest+1,&RFds,&WFds,0,&tv);
+      }
+      while (Res < 0 && errno == EINTR);
+      
       if (Res < 0)
       {
 	 _error->Errno("select","Select has failed");

+ 73 - 19
apt-pkg/contrib/fileutl.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: fileutl.cc,v 1.22 1999/03/15 08:10:39 jgg Exp $
+// $Id: fileutl.cc,v 1.23 1999/03/16 00:43:55 jgg Exp $
 /* ######################################################################
    
    File Utilities
@@ -38,14 +38,21 @@ bool CopyFile(FileFd &From,FileFd &To)
    
    // Buffered copy between fds
    unsigned char *Buf = new unsigned char[64000];
-   long Size;
-   while ((Size = read(From.Fd(),Buf,64000)) > 0)
+   unsigned long Size = From.Size();
+   while (Size != 0)
    {
-      if (To.Write(Buf,Size) == false)
+      unsigned long ToRead = Size;
+      if (Size > 64000)
+	 ToRead = 64000;
+      
+      if (To.Read(Buf,ToRead) == false || 
+	  To.Write(Buf,ToRead) == false)
       {
 	 delete [] Buf;
 	 return false;
       }
+      
+      Size -= ToRead;
    }
 
    delete [] Buf;
@@ -175,14 +182,28 @@ bool WaitFd(int Fd,bool write,unsigned long timeout)
    tv.tv_sec = timeout;
    tv.tv_usec = 0;
    if (write == true) 
-   {
-      if (select(Fd+1,0,&Set,0,(timeout != 0?&tv:0)) <= 0)
-         return false;
+   {      
+      int Res;
+      do
+      {
+	 Res = select(Fd+1,0,&Set,0,(timeout != 0?&tv:0));
+      }
+      while (Res < 0 && errno == EINTR);
+      
+      if (Res <= 0)
+	 return false;
    } 
    else 
    {
-      if (select(Fd+1,&Set,0,0,(timeout != 0?&tv:0)) <= 0)
-         return false;
+      int Res;
+      do
+      {
+	 Res = select(Fd+1,&Set,0,0,(timeout != 0?&tv:0));
+      }
+      while (Res < 0 && errno == EINTR);
+      
+      if (Res <= 0)
+	 return false;
    }
    
    return true;
@@ -239,16 +260,33 @@ FileFd::~FileFd()
 									/*}}}*/
 // FileFd::Read - Read a bit of the file				/*{{{*/
 // ---------------------------------------------------------------------
-/* */
+/* We are carefull to handle interruption by a signal while reading 
+   gracefully. */
 bool FileFd::Read(void *To,unsigned long Size)
 {
-   if (read(iFd,To,Size) != (signed)Size)
+   int Res;
+   errno = 0;
+   do
    {
-      Flags |= Fail;
-      return _error->Errno("read","Read error");
-   }   
+      Res = read(iFd,To,Size);
+      if (Res < 0 && errno == EINTR)
+	 continue;
+      if (Res < 0)
+      {
+	 Flags |= Fail;
+	 return _error->Errno("read","Read error");
+      }
       
-   return true;
+      To = (char *)To + Res;
+      Size -= Res;
+   }
+   while (Res > 0 && Size > 0);
+   
+   if (Size == 0)
+      return true;
+   
+   Flags |= Fail;
+   return _error->Error("read, still have %u to read but none left",Size);
 }
 									/*}}}*/
 // FileFd::Write - Write to the file					/*{{{*/
@@ -256,13 +294,29 @@ bool FileFd::Read(void *To,unsigned long Size)
 /* */
 bool FileFd::Write(const void *From,unsigned long Size)
 {
-   if (write(iFd,From,Size) != (signed)Size)
+   int Res;
+   errno = 0;
+   do
    {
-      Flags |= Fail;
-      return _error->Errno("write","Write error");
+      Res = write(iFd,From,Size);
+      if (Res < 0 && errno == EINTR)
+	 continue;
+      if (Res < 0)
+      {
+	 Flags |= Fail;
+	 return _error->Errno("write","Write error");
+      }
+      
+      From = (char *)From + Res;
+      Size -= Res;
    }
+   while (Res > 0 && Size > 0);
    
-   return true;
+   if (Size == 0)
+      return true;
+   
+   Flags |= Fail;
+   return _error->Error("write, still have %u to write but couldn't",Size);
 }
 									/*}}}*/
 // FileFd::Seek - Seek in the file					/*{{{*/

+ 4 - 1
apt-pkg/contrib/strutl.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: strutl.cc,v 1.21 1999/03/15 08:10:39 jgg Exp $
+// $Id: strutl.cc,v 1.22 1999/03/16 00:43:55 jgg Exp $
 /* ######################################################################
 
    String Util - Some usefull string functions.
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <errno.h>
 									/*}}}*/
 
 // strstrip - Remove white space from the front and back of a string	/*{{{*/
@@ -529,6 +530,8 @@ bool ReadMessages(int Fd, vector<string> &List)
    while (1)
    {
       int Res = read(Fd,End,sizeof(Buffer) - (End-Buffer));
+      if (Res < 0 && errno == EINTR)
+	 continue;
       
       // Process is dead, this is kind of bad..
       if (Res == 0)

+ 13 - 3
cmdline/acqprogress.cc

@@ -1,6 +1,6 @@
 // -*- mode: cpp; mode: fold -*-
 // Description								/*{{{*/
-// $Id: acqprogress.cc,v 1.10 1999/02/27 22:29:11 jgg Exp $
+// $Id: acqprogress.cc,v 1.11 1999/03/16 00:43:55 jgg Exp $
 /* ######################################################################
 
    Acquire Progress - Command line progress meter 
@@ -12,7 +12,9 @@
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/acquire-worker.h>
 #include <apt-pkg/strutl.h>
+
 #include <stdio.h>
+#include <signal.h>
 									/*}}}*/
 
 // AcqTextStatus::AcqTextStatus - Constructor				/*{{{*/
@@ -209,7 +211,13 @@ void AcqTextStatus::Pulse(pkgAcquire *Owner)
    if (Shown == false)
       snprintf(S,End-S," [Working]");
       
-   // Put in the ETA and cps meter
+   /* Put in the ETA and cps meter, block off signals to prevent strangeness
+      during resizing */
+   sigset_t Sigs,OldSigs;
+   sigemptyset(&Sigs);
+   sigaddset(&Sigs,SIGWINCH);
+   sigprocmask(SIG_BLOCK,&Sigs,&OldSigs);
+   
    if (CurrentCPS != 0)
    {      
       char Tmp[300];
@@ -224,7 +232,9 @@ void AcqTextStatus::Pulse(pkgAcquire *Owner)
       }      
    }
    Buffer[ScreenWidth] = 0;
-   
+   BlankLine[ScreenWidth] = 0;
+   sigprocmask(SIG_UNBLOCK,&OldSigs,0);
+
    // Draw the current status
    if (strlen(Buffer) == strlen(BlankLine))
       cout << '\r' << Buffer << flush;