Skip to content

Commit

Permalink
Fix handling of failures when creating local print queues
Browse files Browse the repository at this point in the history
When the function create_queue() fails to create a local print queue
and the failure is not intermittent, it sets a global variable so that
the loop for updating the local print queues for all entries in the
list of discovered remote printers gets stopped and the failing entry
removed from the list of discovered remote printers.

There were two problems with this variable:

- Once the loop stopped, the variable did not get reset, preventing
  any further updating of the local print queues during the rest of
  the life of the daemon. With the print queues not being updated, the
  entries in the remote printer list for which an update is due, stay
  in that state, making update_cups_queues() being called again
  immediately, not updating the queues again, ending up in a busy
  loop, making the daemon run on 100% CPU for the rest of its life.

- create_queue() is running in a background thread, asynchronously,
  meaning that when it sets the global variable on a failure, the loop
  in update_cups_queues() can already have advanced by some list
  entries when it gets stopped, and so the wrong entry gets removed.

Therefore we do away completely with this global variable and simply
mark the failing printer list entry as disappeared so that in the next
run of update_cups_queues() it gets removed.
  • Loading branch information
tillkamppeter committed May 25, 2023
1 parent 1921fa7 commit cb11540
Showing 1 changed file with 3 additions and 11 deletions.
14 changes: 3 additions & 11 deletions daemon/cups-browsed.c
Expand Up @@ -479,7 +479,6 @@ static size_t NumBrowsePoll = 0;
static guint update_netifs_sourceid = 0;
static char local_server_str[1024];
static char *DomainSocket = NULL;
static int cannot_create = 0;
static int cups_queues_updated = 0;
static int update_count = 0;
static unsigned int HttpLocalTimeout = 5;
Expand Down Expand Up @@ -8494,7 +8493,6 @@ create_queue(void* arg)
p->status = STATUS_DISAPPEARED;
current_time = time(NULL);
p->timeout = current_time + TIMEOUT_IMMEDIATELY;
cannot_create = 1;
free((char*)loadedppd);
free(ppdfile);
goto end;
Expand Down Expand Up @@ -8590,7 +8588,6 @@ create_queue(void* arg)
p->status = STATUS_DISAPPEARED;
current_time = time(NULL);
p->timeout = current_time + TIMEOUT_IMMEDIATELY;
cannot_create = 1;
goto end;
}
else
Expand Down Expand Up @@ -8696,7 +8693,9 @@ create_queue(void* arg)
{
debug_printf("get-printer-attributes IPP call failed on printer %s (%s).\n",
p->queue_name, p->uri);
cannot_create = 1;
p->status = STATUS_DISAPPEARED;
current_time = time(NULL);
p->timeout = current_time + TIMEOUT_IMMEDIATELY;
goto end;
}
num_cluster_printers = 0;
Expand Down Expand Up @@ -8780,7 +8779,6 @@ create_queue(void* arg)
p->status = STATUS_DISAPPEARED;
current_time = time(NULL);
p->timeout = current_time + TIMEOUT_IMMEDIATELY;
cannot_create = 1;
goto end;
}
else
Expand Down Expand Up @@ -9321,8 +9319,6 @@ update_cups_queues(gpointer unused)
for (p = (remote_printer_t *)cupsArrayFirst(remote_printers);
p; p = (remote_printer_t *)cupsArrayNext(remote_printers))
{
if (cannot_create) goto cannot_create;

// We need to get the current time as precise as possible for retries
// and reset the timeout flag
current_time = time(NULL);
Expand Down Expand Up @@ -9632,10 +9628,6 @@ update_cups_queues(gpointer unused)
if (p->timeout <= current_time + pause_between_cups_queue_updates)
p->timeout = current_time + pause_between_cups_queue_updates;

cannot_create:
if (p && !in_shutdown)
remove_printer_entry(p);

log_all_printers();
pthread_rwlock_unlock(&update_lock);

Expand Down

0 comments on commit cb11540

Please sign in to comment.