We already set fetchTimeout to 10 seconds, but this does not apply for some
of the connection setup steps such as connect(). This left us hanging in a
few places where we would normally be stuck in a system call for an
indeterminate amount of time.
This addresses FS#15369, which has grown to include and duplicate several
other bugs and failures such as specifying a non-existent FTP server, DSL
disconnections, etc.
Signed-off-by: Dan McGee <dan@archlinux.org>
---
Anyone that wants to look this over, it was pretty simple and kills one of our
long-lingering issues before a 3.5.0 release.
The output isn't necessarily beautiful, but it at least doesn't hang forever
now. I tested this by adding a line like
Server = ftp://192.168.4.4/$repo/os/$arch
to my /etc/pacman.d/mirrorlist file, and then running pacman -Sy.
$ sudo ./src/pacman/pacman -Sy
Password:
:: Synchronizing package databases...
testing is up to date
error: failed retrieving file 'core.db' from 192.168.4.4 : Interrupted system call
core is up to date
error: failed retrieving file 'extra.db' from 192.168.4.4 : Interrupted system call
extra is up to date
community-testing is up to date
error: failed retrieving file 'multilib.db' from 192.168.4.4 : Interrupted system call
multilib is up to date
error: failed retrieving file 'community.db' from 192.168.4.4 : Interrupted system call
community is up to date
+ sig_alrm[NEW].sa_handler = &inthandler;
+ sigemptyset(&sig_alrm[NEW].sa_mask);
+ sig_alrm[NEW].sa_flags = 0;
+ sigaction(SIGALRM, NULL, &sig_alrm[OLD]);
+ sigaction(SIGALRM, &sig_alrm[NEW], NULL);
+
/* NOTE: libfetch does not reset the error code, be sure to do it before
* calls into the library */
@@ -184,7 +190,9 @@ static int download_internal(const char *url, const char *localpath,
* trouble in trying to do both size and "if-modified-since" logic in a
* non-stat request, so avoid it. */
fetchLastErrCode = 0;
+ alarm(fetchTimeout);
if(fetchStat(fileurl, &ust, "") == -1) {
+ alarm(0);
pm_errno = PM_ERR_LIBFETCH;
_alpm_log(PM_LOG_ERROR, _("failed retrieving file '%s' from %s : %s
"),
filename, gethost(fileurl), fetchLastErrString);
@@ -211,6 +219,7 @@ static int download_internal(const char *url, const char *localpath,
}
/* did the transfer complete normally? */
if (nread == -1) {
@@ -333,10 +345,11 @@ cleanup:
fetchFreeURL(fileurl);
/* restore the old signal handlers */
+ sigaction(SIGALRM, &sig_alrm[OLD], NULL);
sigaction(SIGINT, &sig_int[OLD], NULL);
sigaction(SIGPIPE, &sig_pipe[OLD], NULL);
/* if we were interrupted, trip the old handler */
- if(dload_interrupted) {
+ if(dload_interrupted == SIGINT) {
raise(SIGINT);
}