*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 2121,2126 **** SET ENABLE_SEQSCAN TO OFF;
--- 2121,2140 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry id="guc-replication-timeout-server" xreflabel="replication_timeout_server">
+       <term><varname>replication_timeout_server</varname> (<type>integer</type>)</term>
+       <indexterm>
+        <primary><varname>replication_timeout_server</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         If the primary server does not receive a reply from a standby server
+         within <varname>replication_timeout_server</> seconds then the
+         primary will terminate the replication connection.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
       </variablelist>
      </sect2>
     </sect1>
*** a/src/backend/replication/walsender.c
--- b/src/backend/replication/walsender.c
***************
*** 73,78 **** bool		am_walsender = false;		/* Am I a walsender process ? */
--- 73,80 ----
  /* User-settable parameters for walsender */
  int			max_wal_senders = 0;	/* the maximum number of concurrent walsenders */
  int			WalSndDelay = 200;	/* max sleep time between some actions */
+ int			replication_timeout_server; /* If the receiver takes too long, time
+ 										 * out and die after this duration */
  
  /*
   * These variables are used similarly to openLogFile/Id/Seg/Off,
***************
*** 89,94 **** static uint32 sendOff = 0;
--- 91,99 ----
   */
  static XLogRecPtr sentPtr = {0, 0};
  
+ /* Remembers the last time the standby has notified the primary of progress */
+ static TimestampTz last_reply_timestamp;
+ 
  /* Flags set by signal handlers for later service in main loop */
  static volatile sig_atomic_t got_SIGHUP = false;
  volatile sig_atomic_t walsender_shutdown_requested = false;
***************
*** 250,255 **** WalSndHandshake(void)
--- 255,265 ----
  						 errmsg("invalid standby handshake message type %d", firstchar)));
  		}
  	}
+ 
+ 	/*
+ 	 * Initialize our timeout checking mechanism.
+ 	 */
+ 	last_reply_timestamp = GetCurrentTimestamp();
  }
  
  /*
***************
*** 618,632 **** WalSndLoop(void)
  				break;
  			if (caughtup && !got_SIGHUP && !walsender_ready_to_stop && !walsender_shutdown_requested)
  			{
! 				/*
! 				 * XXX: We don't really need the periodic wakeups anymore,
! 				 * WaitLatchOrSocket should reliably wake up as soon as
! 				 * something interesting happens.
! 				 */
  
  				/* Sleep */
! 				WaitLatchOrSocket(&MyWalSnd->latch, MyProcPort->sock,
! 								  WalSndDelay * 1000L);
  			}
  		}
  		else
--- 628,649 ----
  				break;
  			if (caughtup && !got_SIGHUP && !walsender_ready_to_stop && !walsender_shutdown_requested)
  			{
! 				long timeout;
! 
! 				if (replication_timeout_server == -1)
! 					timeout = -1L;
! 				else
! 					timeout = 1000000L * replication_timeout_server;
  
  				/* Sleep */
! 				if (WaitLatchOrSocket(&MyWalSnd->latch, MyProcPort->sock,
! 									  timeout) == 0)
! 				{
! 					ereport(LOG,
! 							(errmsg("streaming replication timeout after %d s",
! 									replication_timeout_server)));
! 					break;
! 				}
  			}
  		}
  		else
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 1484,1489 **** static struct config_int ConfigureNamesInt[] =
--- 1484,1499 ----
  	},
  
  	{
+ 		{"replication_timeout_server", PGC_SIGHUP, WAL_SETTINGS,
+ 		 gettext_noop("Replication connection will timeout after this duration."),
+ 		 NULL,
+ 		 GUC_UNIT_S
+ 		},
+ 		&replication_timeout_server,
+ 		30, -1, INT_MAX, NULL, NULL
+ 	},
+ 
+ 	{
  		{"temp_buffers", PGC_USERSET, RESOURCES_MEM,
  			gettext_noop("Sets the maximum number of temporary buffers used by each session."),
  			NULL,
***************
*** 1828,1843 **** static struct config_int ConfigureNamesInt[] =
  	},
  
  	{
- 		{"wal_sender_delay", PGC_SIGHUP, WAL_REPLICATION,
- 			gettext_noop("WAL sender sleep time between WAL replications."),
- 			NULL,
- 			GUC_UNIT_MS
- 		},
- 		&WalSndDelay,
- 		200, 1, 10000, NULL, NULL
- 	},
- 
- 	{
  		{"commit_delay", PGC_USERSET, WAL_SETTINGS,
  			gettext_noop("Sets the delay in microseconds between transaction commit and "
  						 "flushing WAL to disk."),
--- 1838,1843 ----
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 203,208 ****
--- 203,209 ----
  					# when reading streaming WAL;
  					# -1 allows indefinite delay
  #wal_receiver_status_interval = 10s	# replies at least this often, 0 disables
+ #replication_timeout_server = 120	# -1 means wait forever
  
  
  #------------------------------------------------------------------------------
*** a/src/include/replication/walsender.h
--- b/src/include/replication/walsender.h
***************
*** 68,75 **** extern volatile sig_atomic_t walsender_shutdown_requested;
  extern volatile sig_atomic_t walsender_ready_to_stop;
  
  /* user-settable parameters */
- extern int	WalSndDelay;
  extern int	max_wal_senders;
  
  extern int	WalSenderMain(void);
  extern void WalSndSignals(void);
--- 68,75 ----
  extern volatile sig_atomic_t walsender_ready_to_stop;
  
  /* user-settable parameters */
  extern int	max_wal_senders;
+ extern int	replication_timeout_server;
  
  extern int	WalSenderMain(void);
  extern void WalSndSignals(void);