Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 276525

Summary: sys-process/vixie-cron-4.1-r10: runs deleted files from /etc/cron.d
Product: Gentoo Linux Reporter: gilhad <gilhad>
Component: [OLD] Core systemAssignee: No maintainer - Look at https://wiki.gentoo.org/wiki/Project:Proxy_Maintainers if you want to take care of it <maintainer-needed>
Status: RESOLVED OBSOLETE    
Severity: minor CC: christoph.gysin, cron-bugs+disabled, kfm, treecleaner
Priority: High Keywords: PMASKED
Version: unspecified   
Hardware: x86   
OS: Linux   
Whiteboard:
Package list:
Runtime testing required: ---
Deadline: 2019-10-11   
Attachments: fix reloading of changed files in /etc/cron.d

Description gilhad 2009-07-05 02:30:42 UTC
sys-process/vixie-cron-4.1-r10 processes files from /etc/cron.d even days after they are deleted.
I had uploaded on remote boxes /home/user/script.sh to do something and added simple one line entry for it to /etc/cron.d (/etc/cron.d.entry)
The script runned like planned (each hour at defined time) and after some days I needed to stop running it at regular time, but i wanted to run it ocassionally on demand, so i deleted the entry in /etc/cron.d
But the script was runned still, as if the file was not deleted. /var/log/cron have entry for this calls and so. Apparently the cron have cached the context of the entry somewhere in memory and even if the entry file is deleted, then cron is using the cached version.

I also tried to:
touch /etc/cron.d
killall -SIGHUP cron
touch /etc/crontab (it got reloaded, but the entry was still in use)
lsof (no open files in /etc/cron.d was found)

/etc/init.d/vixie-cron restart  (this one ofcourse helped, but it is not, what i would like to do regulary)

Reproducible: Always

Steps to Reproduce:
1. create script /home/user/script.sh, make it executable, make it append time to some log file at each run (
$cat /home/user/script.sh
#!/bin/bash
date >> /home/user/logfile
)
2. cerate entry for it in /etc/cron.d (
# cat /etc/cron.d/entry
PATH=/usr/local/bin:/usr/bin:/bin:/opt/bin
20 * * * * user /home/usr/script.sh &>/dev/null
)
3. after some time delete the entry
rm  /etc/cron.d/entry

Actual Results:  
the script is executed even after the entry is deleted. The /home/user/logfile is increasind and contains all the times. /var/log/cron shows the /home/usr/script.sh is being executed regardles the /etc/cron.d/entry is long time (like in days) deleted

Expected Results:  
after deleting /etc/cron.d/entry the cron on next minute would find the file does not exist and so the /home/usr/script.sh is not executed anymore

(alternatively have some way like touching file/directory, or sending signal to cron which would simply force the cron to forgot everything and re-read ALL files to run only what really exists)

Happens on many different boxes to me. the same routine. the same problem.

Severity: there is ugly workaround, but it is ugly way. It would be good, if it get fixed, or at least explained (and added to man cron), why it would be this way.
Comment 1 Christoph Gysin 2009-08-14 07:46:26 UTC
I can confirm this. There are multiple problems with the /etc/cron.d patch, vixie-cron-4.1-gentoo-r4.patch.bz2:

@@ -53,6 +53,11 @@
 		(void) exit(ERROR_EXIT);
 	}
 
+	if (stat("/etc/cron.d", &crond_stat) < OK) {
+		log_it("CRON", getpid(), "STAT FAILED", SPOOL_DIR);

Wrong log entry, SPOOL_DIR is supposed to be "/etc/cron.d".

@@ -76,13 +82,43 @@
 	 * actually changed.  Whatever is left in the old database when
 	 * we're done is chaff -- crontabs that disappeared.
 	 */
-	new_db.mtime = TMAX(statbuf.st_mtime, syscron_stat.st_mtime);
+	new_db.mtime = TMAX(crond_stat.st_mtime,
+			    TMAX(statbuf.st_mtime, syscron_stat.st_mtime));

This only takes mtime from /etc/cron.d dir, ignoring changed files within.

 	new_db.head = new_db.tail = NULL;
 
 	if (syscron_stat.st_mtime)
 		process_crontab("root", NULL, SYSCRONTAB, &syscron_stat,
 				&new_db, old_db);
 
+	if (!(dir = opendir("/etc/cron.d"))) {
+		log_it("CRON", getpid(), "OPENDIR FAILED", "/etc/cron.d");
+		(void) exit(ERROR_EXIT);
+	}
+
+	while (NULL != (dp = readdir(dir))) {
+		char	fname[MAXNAMLEN+1],
+			tabname[MAXNAMLEN+1];
+
+		/* avoid file names beginning with ".".  this is good
+		 * because we would otherwise waste two guaranteed calls
+		 * to getpwnam() for . and .., and there shouldn't be 
+		 * hidden files in here anyway. Also ignore files beginning
+		 * with '#' and ending with '~'.
+		 */
+		if (dp->d_name[0] == '.' ||
+		    dp->d_name[0] == '#' ||
+		    dp->d_name[strlen(dp->d_name) - 1] == '~')
+			continue;
+
+		(void) strncpy(fname, dp->d_name, MAXNAMLEN);
+		snprintf(tabname, MAXNAMLEN+1, "/etc/cron.d/%s", fname);
+
+		process_crontab("root", NULL, tabname,
+				&crond_stat, &new_db, old_db);

The NULL here will make process_crontab() use "*system*" as user, and also as key to store in the database. We need unique identifiers though, so I suggest using the full path of the file as key.

Patch follows.
Comment 2 Christoph Gysin 2009-08-14 07:52:23 UTC
Created attachment 201206 [details, diff]
fix reloading of changed files in /etc/cron.d

This fixes reloading of files within /etc/cron.d/ based on mtime.

It *still* only checks for changed files within /etc/cron.d if /etc/cron.d's mtime has changed! If you edit the file in place (open/truncate/write/close) the directory won't get changed and cron will not reread the file.

This is actually the same behavior as in /var/spool/cron/crontabs, but there you would usually use "crontab -e" anyways, which will update the directory's mtime.
Comment 3 Christoph Gysin 2009-08-14 07:54:25 UTC
gilhad, I hope you're still on to this. Would you please test if this works for you?
Comment 4 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2019-10-11 15:07:51 UTC
Package removed.