Bug#710803: cron: systematically creates a temporary file in /tmp every hour

2013-06-09 Thread Christian Kastner
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 2013-06-07 15:55, Saint Germain wrote:
 On 5 June 2013 23:34, Christian Kastner deb...@kvr.at wrote:
 On 2013-06-05 13:12, Saint Germain wrote:
 Indeed even if cron has nothing to do, a temporary file is 
 always created in /tmp and immediatly deleted.
 
 So another workaround for you would be to comment out the hourly 
 stanza from /etc/crontab.
 
 Any other solution would be overly complex to implement, I'm
 afraid.
 
 Ok I haven't carefully read the commit, so I didn't understand why 
 this file creation was necessary in the first place (and why other 
 distro don't have this behavior).

To prevent data loss.

Summarized: one of cron's features is the mailing of output. Regular
cron connects to the MTA, runs the job and pipes its output to the
MTA. However, some MTAs time out if they don't receive input within a
certain amount of time, resulting in the output not being sent by
mail, resulting in data loss (see bugs #155109, #443615).

With the patch, we write to a tmpfile and only connect to the MTA when
the job is finished, thereby preventing this possible data loss.

 If mounting /tmp on a tmpfs as a workaround is acceptable,
 probably that creating the temporary file directly in RAM would
 also be acceptable ?

That came to my mind as a possible solution, too. The problem is we
don't know how much RAM we might have available (think embedded
systems), so consuming possibly large amounts of it periodicalyly may
result in Bad Stuff(tm) happening to the system.

An alternative could be to control this behaviour (pipe to MTA
directly vs pipe to tmpfile) via a command-line flag.

 Hum, that is a very hot question that was discussed many many
 times: http://lwn.net/Articles/499534/
 
 I think it is better to avoid discussing too much this particular
 hot topic /tmp on tmpfs. ;-)

Good point :-)

-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAlG0k6oACgkQwSyarY0epjXVlgCfS089H4fOvWeTWOQ7Wm53ALBv
/B4AnjGRYT7jyXeLVw7nHx7UOcBGNrXA
=seE+
-END PGP SIGNATURE-


-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#710803: cron: systematically creates a temporary file in /tmp every hour

2013-06-09 Thread Saint Germain
On Sunday, 9 June 2013, Christian Kastner deb...@kvr.at wrote:
 -BEGIN PGP SIGNED MESSAGE-
 Hash: SHA1

 On 2013-06-07 15:55, Saint Germain wrote:
 On 5 June 2013 23:34, Christian Kastner deb...@kvr.at wrote:
 On 2013-06-05 13:12, Saint Germain wrote:
 Indeed even if cron has nothing to do, a temporary file is
 always created in /tmp and immediatly deleted.

 So another workaround for you would be to comment out the hourly
 stanza from /etc/crontab.

 Any other solution would be overly complex to implement, I'm
 afraid.

 Ok I haven't carefully read the commit, so I didn't understand why
 this file creation was necessary in the first place (and why other
 distro don't have this behavior).

 To prevent data loss.

 Summarized: one of cron's features is the mailing of output. Regular
 cron connects to the MTA, runs the job and pipes its output to the
 MTA. However, some MTAs time out if they don't receive input within a
 certain amount of time, resulting in the output not being sent by
 mail, resulting in data loss (see bugs #155109, #443615).

 With the patch, we write to a tmpfile and only connect to the MTA when
 the job is finished, thereby preventing this possible data loss.

 If mounting /tmp on a tmpfs as a workaround is acceptable,
 probably that creating the temporary file directly in RAM would
 also be acceptable ?

 That came to my mind as a possible solution, too. The problem is we
 don't know how much RAM we might have available (think embedded
 systems), so consuming possibly large amounts of it periodicalyly may
 result in Bad Stuff(tm) happening to the system.

 An alternative could be to control this behaviour (pipe to MTA
 directly vs pipe to tmpfile) via a command-line flag.


OK got it !
Thanks for having taken the time to explain. A command-line flag would be
ideal, I agree.

Best regards,


Bug#710803: cron: systematically creates a temporary file in /tmp every hour

2013-06-09 Thread Justin T Pryzby
Hi Christian,

From memory, I believe debian already patches cron in one other way to
avoid spinning up laptop drives (I believe it's related to stat()ing
/etc/cron.d to check for updated files?).  I believe we should aim to
fix this here, too.  I'm attaching a very lightly tested patch.  Note
this also fixes a bug in the existing cron tmpfile patch regarding
fwrite()ing of the tmpfile buffer to the popen()ed mail command.  In
the case of an incomplete write(), the bug causes the beginning of the
buffer to be written again, rather than resuming where it left off,
essentially resulting in data loss off the last portion of the buffer.
--- ../orig/do_command.c2013-06-09 15:37:45.0 -0700
+++ ./do_command.c  2013-06-09 16:37:36.0 -0700
@@ -127,7 +127,7 @@
user*u;
 {
int stdin_pipe[2];
-   FILE*tmpout;
+   int stdout_pipe[2];
register char   *input_data;
char*usernm, *mailto;
int children = 0;
@@ -191,12 +191,8 @@
/* create a pipe to talk to our future child
 */
pipe(stdin_pipe);   /* child's stdin */
-   /* child's stdout */
-   if ((tmpout = tmpfile()) == NULL) {
-   log_it(CRON, getpid(), error, create tmpfile);
-   exit(ERROR_EXIT);
-   }
-   
+   pipe(stdout_pipe);  /* child's stdout */
+
/* since we are a forked process, we can diddle the command string
 * we were passed -- nobody else is going to use it again, right?
 *
@@ -284,6 +280,7 @@
 * appropriate circumstances.
 */
close(stdin_pipe[WRITE_PIPE]);
+   close(stdout_pipe[READ_PIPE]);
 
/* grandchild process.  make std{in,out} be the ends of
 * pipes opened by our daddy; make stderr go to stdout.
@@ -291,14 +288,15 @@
/* Closes are unnecessary -- let dup2() do it */
 
  /* close(STDIN) */; dup2(stdin_pipe[READ_PIPE], STDIN);
- dup2(fileno(tmpout), STDOUT);
  /* close(STDERR)*/; dup2(STDOUT, STDERR);
 
-
/* close the pipe we just dup'ed.  The resources will remain.
 */
close(stdin_pipe[READ_PIPE]);
-   fclose(tmpout);
+
+   // dup2(fileno(tmpout), STDOUT);
+   dup2(stdout_pipe[WRITE_PIPE], STDOUT);
+   close(stdout_pipe[WRITE_PIPE]);
 
/* set our login universe.  Do this in the grandchild
 * so that the child can invoke /usr/lib/sendmail
@@ -404,6 +402,7 @@
 * grandchild process...
 */
close(stdin_pipe[READ_PIPE]);
+   close(stdout_pipe[WRITE_PIPE]);
 
/*
 * write, to the pipe connected to child's stdin, any input specified
@@ -465,8 +464,8 @@
children++;
 
/*
-* read output from the grandchild.  it's stderr has been redirected to
-* it's stdout, which has been redirected to our pipe.  if there is any
+* read output from the grandchild.  its stderr has been redirected to
+* its stdout, which has been redirected to our pipe.  if there is any
 * output, we'll be mailing it to the user whose crontab this is...
 * when the grandchild exits, we'll get EOF.
 */
@@ -506,23 +505,50 @@
}
}
 
+// Read the output of the command, save it into a tempfile.  This
+// doesn't write to a tempfile directly to avoid creating tempfiles
+// and spinning up laptop drives, even when only run-parts is the
+// only, empty job run.
+
+   FILE *tmpout;
+   char buf[19];
+   int ret, remain;
+
+   // if no output, done:
+   if (read(stdout_pipe[READ_PIPE], buf, 1)==0)
+   goto mail_finished;
+
+   // else collect it all in tmpfile:
+   if ((tmpout = tmpfile()) == NULL) {
+   log_it(CRON, getpid(), error, create tmpfile);
+   goto mail_finished;
+   }
+
+   putc(*buf, tmpout);
+   for ( ; ret=read(stdout_pipe[READ_PIPE], buf, sizeof(buf)); ) {
+   char *pos;
+   for (pos=buf, remain=ret; remain!=0; ) {
+   int x=fwrite(buf, 1, remain, tmpout);
+   if (x0) {
+   remain -= ret;
+   pos+=ret;
+   }
+   }
+   }
+
+   
 // Finally, send any output of the command to the mailer; also, alert
 // the user if their job failed.  Avoid popening the mailcmd until now
 // since sendmail may time out, and to write info about the exit
 // status.
-   
-   long pos;
+   register FILE   *mail = NULL;
+   register intbytes = 1;
+
struct stat mcsb;
int statret;
 
-   fseek(tmpout, 0, SEEK_END);
-   pos = ftell(tmpout);
-   fseek(tmpout, 0, 

Bug#710803: cron: systematically creates a temporary file in /tmp every hour

2013-06-07 Thread Saint Germain
On 5 June 2013 23:34, Christian Kastner deb...@kvr.at wrote:
 On 2013-06-05 13:12, Saint Germain wrote:
 Indeed even if cron has nothing to do, a temporary file is
 always created in /tmp and immediatly deleted.

 nothing to do = there is no job (cron.hourly is empty and users
 cron are empty)

 However it would more elegant for cron to skip this file creation
 in case there is no job to execute.

 Ah, but there is one job running: run-parts.

 The scripts in cron.{hourly,daily,weekly,monthly} are not processed by
 the cron daemon directly. Instead, the system crontab /etc/crontab
 contains schedules for calls to run-parts /etc/cron.[interval], and
 run-parts then processes those scripts. From cron's POV, there is
 always exactly 1 process being run.

 So another workaround for you would be to comment out the hourly
 stanza from /etc/crontab.

 Any other solution would be overly complex to implement, I'm afraid.

Ok I haven't carefully read the commit, so I didn't understand why
this file creation was necessary in the first place (and why other
distro don't have this behavior).
If mounting /tmp on a tmpfs as a workaround is acceptable, probably
that creating the temporary file directly in RAM would also be
acceptable ?
Anyway, as you are the maintainer, I think you are much knowledgeable
than me to decide what is best for Debian.

 This is only a minor bug though, but I spent quite a long time
 tracking it (especially given that only Debian users have this bug)
 so I thought that it may be useful to report it.

 I agree, thank you.

 I can of course mount /tmp on a tmpfs, but it seems to me that it
 would be overkill (as cron is the only software I have which
 behaves like this). A better workaround would be for me to simply
 comment the line cron.hourly in /etc/crontab (as I don't have any
 hourly job).

 (Off-topic, personal opinion: having a tmpfs on /tmp has many other
 benefits, eg: there is no need to clean the filesystem on boot. Most of
 the stuff in /tmp is probably going to be cached, ie in RAM, anyway)

Hum, that is a very hot question that was discussed many many times:
http://lwn.net/Articles/499534/

I think it is better to avoid discussing too much this particular hot
topic /tmp on tmpfs. ;-)


-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#710803: cron: systematically creates a temporary file in /tmp every hour

2013-06-05 Thread Christian Kastner
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

 It seems that the following Debian commit which introduces a
 temporary file has an unfortunate side-effect: 
 http://anonscm.debian.org/gitweb/?p=pkg-cron/pkg- 
 cron.git;a=commitdiff;h=e61050367866fb1b627e2c004d370914eced70cb
 
 Indeed even if cron has nothing to do, a temporary file is always
 created in /tmp and immediatly deleted.
 
 I am trying to reduce the power consumption of my server and this
 patch had the effect of waking-up the hard-drive every hour.
 
 Maybe it is possible to prevent the temporary file creation if cron
 has nothing to do ?

With nothing to do, do mean no jobs are run or jobs do not create
output?

In any case, a simple solution would be to have a tmpfs on /tmp. This
is trivial to do with Wheezy (see /etc/default/tmpfs), and still easy
with Squeeze.

Christian
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAlGu//wACgkQwSyarY0epjX6JgCeNJ9KM7vpudKvueQ+EBERNpQo
jeIAnjNXziel3gQ+H2sHRqiR7FOPxijW
=5oHu
-END PGP SIGNATURE-


-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#710803: cron: systematically creates a temporary file in /tmp every hour

2013-06-05 Thread Saint Germain
On 5 June 2013 11:08, Christian Kastner deb...@kvr.at wrote:
 -BEGIN PGP SIGNED MESSAGE-
 Hash: SHA1

 It seems that the following Debian commit which introduces a
 temporary file has an unfortunate side-effect:
 http://anonscm.debian.org/gitweb/?p=pkg-cron/pkg-
 cron.git;a=commitdiff;h=e61050367866fb1b627e2c004d370914eced70cb

 Indeed even if cron has nothing to do, a temporary file is always
 created in /tmp and immediatly deleted.

 I am trying to reduce the power consumption of my server and this
 patch had the effect of waking-up the hard-drive every hour.

 Maybe it is possible to prevent the temporary file creation if cron
 has nothing to do ?

 With nothing to do, do mean no jobs are run or jobs do not create
 output?

 In any case, a simple solution would be to have a tmpfs on /tmp. This
 is trivial to do with Wheezy (see /etc/default/tmpfs), and still easy
 with Squeeze.

nothing to do = there is no job (cron.hourly is empty and users cron
are empty)

I can of course mount /tmp on a tmpfs, but it seems to me that it
would be overkill (as cron is the only software I have which behaves
like this). A better workaround would be for me to simply comment the
line cron.hourly in /etc/crontab (as I don't have any hourly job).

However it would more elegant for cron to skip this file creation in
case there is no job to execute.
This is only a minor bug though, but I spent quite a long time
tracking it (especially given that only Debian users have this bug) so
I thought that it may be useful to report it.

Best regards,


-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#710803: cron: systematically creates a temporary file in /tmp every hour

2013-06-05 Thread Christian Kastner
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 2013-06-05 13:12, Saint Germain wrote:
 Indeed even if cron has nothing to do, a temporary file is
 always created in /tmp and immediatly deleted.
 
 I am trying to reduce the power consumption of my server and
 this patch had the effect of waking-up the hard-drive every
 hour.
 
 Maybe it is possible to prevent the temporary file creation if
 cron has nothing to do ?
 
 With nothing to do, do mean no jobs are run or jobs do not
 create output?
 
 nothing to do = there is no job (cron.hourly is empty and users
 cron are empty)
 
 However it would more elegant for cron to skip this file creation
 in case there is no job to execute.

Ah, but there is one job running: run-parts.

The scripts in cron.{hourly,daily,weekly,monthly} are not processed by
the cron daemon directly. Instead, the system crontab /etc/crontab
contains schedules for calls to run-parts /etc/cron.[interval], and
run-parts then processes those scripts. From cron's POV, there is
always exactly 1 process being run.

So another workaround for you would be to comment out the hourly
stanza from /etc/crontab.

Any other solution would be overly complex to implement, I'm afraid.

 This is only a minor bug though, but I spent quite a long time 
 tracking it (especially given that only Debian users have this bug)
 so I thought that it may be useful to report it.

I agree, thank you.

 I can of course mount /tmp on a tmpfs, but it seems to me that it 
 would be overkill (as cron is the only software I have which
 behaves like this). A better workaround would be for me to simply
 comment the line cron.hourly in /etc/crontab (as I don't have any
 hourly job).

(Off-topic, personal opinion: having a tmpfs on /tmp has many other
benefits, eg: there is no need to clean the filesystem on boot. Most of
the stuff in /tmp is probably going to be cached, ie in RAM, anyway)
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAlGvrsoACgkQwSyarY0epjXFaQCg3PL4cROPSawxFfaRzHDGXUJl
X9cAoI4EgvV4HH4z9K61+wkYcXARj9kF
=P7UF
-END PGP SIGNATURE-


-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org



Bug#710803: cron: systematically creates a temporary file in /tmp every hour

2013-06-02 Thread SaintGermain
Package: cron
Version: 3.0pl1-124
Severity: minor

Dear Maintainer,

It seems that the following Debian commit which introduces a temporary file has
an unfortunate side-effect:
http://anonscm.debian.org/gitweb/?p=pkg-cron/pkg-
cron.git;a=commitdiff;h=e61050367866fb1b627e2c004d370914eced70cb

Indeed even if cron has nothing to do, a temporary file is always created in
/tmp and immediatly deleted.

I am trying to reduce the power consumption of my server and this patch had the
effect of waking-up the hard-drive every hour.

Maybe it is possible to prevent the temporary file creation if cron has nothing
to do ?

Best regards



-- Package-specific info:
--- EDITOR:


--- /usr/bin/editor:
/bin/nano

--- /usr/bin/crontab:
-rwxr-sr-x 1 root crontab 34760 Jul  3  2012 /usr/bin/crontab

--- /var/spool/cron:
drwxr-xr-x 5 root root 4096 Nov  1  2010 /var/spool/cron

--- /var/spool/cron/crontabs:
drwx-wx--T 2 root crontab 4096 Oct 16  2010 /var/spool/cron/crontabs

--- /etc/cron.d:
drwxr-xr-x 2 root root 4096 May  4 20:56 /etc/cron.d

--- /etc/cron.daily:
drwxr-xr-x 2 root root 4096 May 15 21:43 /etc/cron.daily

--- /etc/cron.hourly:
drwxr-xr-x 2 root root 4096 Aug 16  2012 /etc/cron.hourly

--- /etc/cron.monthly:
drwxr-xr-x 2 root root 4096 Aug 16  2012 /etc/cron.monthly

--- /etc/cron.weekly:
drwxr-xr-x 2 root root 4096 May 15 21:42 /etc/cron.weekly


-- System Information:
Debian Release: jessie/sid
  APT prefers testing
  APT policy: (900, 'testing'), (500, 'oldstable'), (90, 'experimental')
Architecture: i386 (i686)

Kernel: Linux 3.2.0-2-686-pae (SMP w/4 CPU cores)
Locale: LANG=fr_FR.utf8, LC_CTYPE=fr_FR.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages cron depends on:
ii  adduser 3.113+nmu3
ii  debianutils 4.3.4
ii  dpkg1.16.10
ii  libc6   2.13-38
ii  libpam-runtime  1.1.3-9
ii  libpam0g1.1.3-9
ii  libselinux1 2.1.9-5
ii  lsb-base4.1+Debian9

Versions of packages cron recommends:
ii  exim4  4.80-7
ii  exim4-daemon-light [mail-transport-agent]  4.80-7

Versions of packages cron suggests:
ii  anacron2.3-19
pn  checksecurity  none
ii  logrotate  3.8.1-4

Versions of packages cron is related to:
pn  libnss-ldap   none
pn  libnss-ldapd  none
pn  libpam-ldap   none
pn  libpam-mount  none
pn  nis   none
pn  nscd  none

-- no debconf information


-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org