Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Jun 2013 16:50:05 +0000 (UTC)
From:      Pietro Cerutti <gahr@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r252034 - stable/8/usr.bin/at
Message-ID:  <201306201650.r5KGo5oF094216@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gahr (ports committer)
Date: Thu Jun 20 16:50:05 2013
New Revision: 252034
URL: http://svnweb.freebsd.org/changeset/base/252034

Log:
  MFC: r249406
  
  - Do not bail out if stat(2) fails with ENOENT in the spool directory. This
    happens if another atrm process removes a job while we're scanning through
    the directory.
  - While at it, optimize a bit the directory scanning, so that we quit
    looping as soon as all jobs specified in argv have been dealt with.
  
  Approved by:	cognet

Modified:
  stable/8/usr.bin/at/at.c
Directory Properties:
  stable/8/usr.bin/at/   (props changed)

Modified: stable/8/usr.bin/at/at.c
==============================================================================
--- stable/8/usr.bin/at/at.c	Thu Jun 20 14:30:16 2013	(r252033)
+++ stable/8/usr.bin/at/at.c	Thu Jun 20 16:50:05 2013	(r252034)
@@ -533,6 +533,10 @@ process_jobs(int argc, char **argv, int 
     /* Delete every argument (job - ID) given
      */
     int i;
+    int rc;
+    int nofJobs;
+    int nofDone;
+    int statErrno;
     struct stat buf;
     DIR *spool;
     struct dirent *dirent;
@@ -540,6 +544,9 @@ process_jobs(int argc, char **argv, int 
     char queue;
     long jobno;
 
+    nofJobs = argc - optind;
+    nofDone = 0;
+
     PRIV_START
 
     if (chdir(ATJOB_DIR) != 0)
@@ -555,9 +562,20 @@ process_jobs(int argc, char **argv, int 
     while((dirent = readdir(spool)) != NULL) {
 
 	PRIV_START
-	if (stat(dirent->d_name, &buf) != 0)
-	    perr("cannot stat in " ATJOB_DIR);
+	rc = stat(dirent->d_name, &buf);
+	statErrno = errno;
 	PRIV_END
+	/* There's a race condition between readdir above and stat here:
+	 * another atrm process could have removed the file from the spool
+	 * directory under our nose. If this happens, stat will set errno to
+	 * ENOENT, which we shouldn't treat as fatal.
+	 */
+	if (rc != 0) {
+	    if (statErrno == ENOENT)
+		continue;
+	    else
+		perr("cannot stat in " ATJOB_DIR);
+	}
 
 	if(sscanf(dirent->d_name, "%c%5lx%8lx", &queue, &jobno, &ctm)!=3)
 	    continue;
@@ -603,9 +621,15 @@ process_jobs(int argc, char **argv, int 
 		    errx(EXIT_FAILURE, "internal error, process_jobs = %d",
 			what);
 	        }
+
+		/* All arguments have been processed
+		 */
+		if (++nofDone == nofJobs)
+		    goto end;
 	    }
 	}
     }
+end:
     closedir(spool);
 } /* delete_jobs */
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201306201650.r5KGo5oF094216>