[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [leafnode-list] interrupted downloads



Mike Castle wrote:
> 
> When a post is being downloaded, it seems to go into message.id/### while
> it's being downloaded, and then linked in afterwards (well, maybe the
> linking occurs after the open, but either way, the entry exists in
> message.id fist).
> 
> Unfortunately, if you c-C fetchnews (say, because something else is going
> wrong and you know you need to reboot), the incomplete entry stays in
> message.id/### and is never completely downloaded.
> [...]

Yes and this is a bug.
There is a solution using the signals functions.
The goal is to block one or more signals in a code section, good exercise to
recall how software interrupts are handled :-)

In the patch joined bellow, there are more lines than needed...

I added also the catch of SIGTERM because this is the default used by the
command kill and used during the shutdown process.
Catching the TERM signal simplify the command to stop a process when running
in the background.
kill `cat /var/lock/news/fetchnews.lck` or kill <pid> or kill %<job number>
will do a clean completion.

This should solve the problem you have rightly mentioned.

N.B. 
- The current file leaf.node/my.news.server is not updated but this is not a
problem.
- This patch works for 1.9.13 and 1.9.14.
- Also includes my preceding patch posted on May 26 (article download order).
- Also suppress the "water marks" reset in case of automatic unsubscription (I
don't like it...).

*** fetchnews.c.org	Sun Apr  9 14:05:11 2000
--- fetchnews.c	Sun Jul  9 10:35:22 2000
***************
*** 14,19 ****
--- 14,20 ----
  Modified by Cornelius Krasel <krasel@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>.
  Copyright of the modifications 1998, 1999.
  
+ Patch applied: 000709 - o.rousseaux@xxxxxxxxxxxxxx / rousse_o@xxxxxxx 
  See file COPYING for restrictions on the use of this software.
  */
  
***************
*** 90,96 ****
  #endif
  
  static void sig_int( int signo ) {
!     if ( signo == SIGINT || signo == SIGTERM )
  	longjmp( jmpbuffer, 1 );
  }
  
--- 91,97 ----
  #endif
  
  static void sig_int( int signo ) {
! 	printf("** caught SIGINT or SIGTERM **\n");
  	longjmp( jmpbuffer, 1 );
  }
  
***************
*** 575,580 ****
--- 576,582 ----
      struct stat st;
      int outstanding = 0, i;
      static int * stufftoget;
+     sigset_t newmask, pendmask;
  
      if ( !g )
  	return server;
***************
*** 663,670 ****
  	    syslog( LOG_INFO, "skip %s (%d): %d, %d", g->name, (int)now,
  		    now-st.st_ctime, now-st.st_mtime );
  	    unlink(s);
- 	    g->first = 1;
- 	    g->last = 1;
  	    return server ;
         }
      }
--- 665,670 ----
***************
*** 678,683 ****
--- 678,684 ----
      if ( server > last ) {
  	if ( verbose > 1 )
  	    printf( "%s: no new articles\n", g->name );
+ 	    syslog( LOG_INFO, "%s: no new articles\n", g->name);
  	return server;
      }
  
***************
*** 784,791 ****
  
      /* now we have a list of articles in stufftoget[] */
      /* let's get the header and possibly bodies of these */
      while ( outstanding > 0 ) {
!         i = outstanding-1;
  	outstanding--;
  	if ( !stufftoget[i] )
  	    continue;
--- 785,801 ----
  
      /* now we have a list of articles in stufftoget[] */
      /* let's get the header and possibly bodies of these */
+     i = -1;
      while ( outstanding > 0 ) {
! 
! 	sigpending(&pendmask);
!         if (sigismember(&pendmask, SIGINT))
!           printf("\n** SIGINT is pending\n");
!         if (sigismember(&pendmask, SIGTERM))
!           printf("\n** SIGTERM is pending\n");
! 	sigemptyset( &newmask );
! 	sigprocmask(SIG_SETMASK, &newmask, NULL);  /* all signals excluded */
!         i++;
  	outstanding--;
  	if ( !stufftoget[i] )
  	    continue;
***************
*** 799,804 ****
--- 809,818 ----
  	    continue;
  	}
  
+ 	sigaddset( &newmask, SIGINT);
+ 	sigaddset( &newmask, SIGTERM);
+ 	sigprocmask(SIG_SETMASK, &newmask, NULL);  /* block SIGINT & SIGTERM */
+ 
  	sprintf(lineout, "HEAD %d\r\n", stufftoget[i]);
  	putaline();
  	l = getaline( nntpin );
***************
*** 1587,1594 ****
  	    forceactive = 1;
      }
  
!     if ( signal( SIGINT, sig_int ) == SIG_ERR )
! 	fprintf( stderr, "Can't catch SIGINT.\n" );
      else if ( setjmp( jmpbuffer ) != 0 ) {
  	servers = NULL;		/* in this case, jump the while ... loop */
      }
--- 1601,1609 ----
  	    forceactive = 1;
      }
  
!     if ( (signal( SIGINT, sig_int ) == SIG_ERR ) ||
!          (signal( SIGTERM, sig_int ) == SIG_ERR ) )
! 	         fprintf( stderr, "Can't catch SIGINT or SIGTERM.\n" );
      else if ( setjmp( jmpbuffer ) != 0 ) {
  	servers = NULL;		/* in this case, jump the while ... loop */
      }