From 7a1c25951e07aec58c8c34bd9446ffbb4b352385 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Dec 2010 14:32:29 +0100 Subject: [PATCH 1/2] s3-printing: remove unneeded local_pcap_copy global The cups local_pcap_copy global served as a temporary buffer during asynchronous cups printcap cache updates, as well as indicating when the printcap cache had not yet been filled and princap cache update should block. As smbd printcap reads are now triggered by the parent smbd following printcap cache update, the variable and blocking mechanism are no longer needed. --- source3/printing/print_cups.c | 54 +++++++++++++--------------------------- 1 files changed, 18 insertions(+), 36 deletions(-) diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c index 0e5dac5..d2df258 100644 --- a/source3/printing/print_cups.c +++ b/source3/printing/print_cups.c @@ -390,8 +390,7 @@ static bool cups_cache_reload_async(int fd) return ret; } -static struct pcap_cache *local_pcap_copy; -struct fd_event *cache_fd_event; +static struct fd_event *cache_fd_event; static bool cups_pcap_load_async(struct tevent_context *ev, struct messaging_context *msg_ctx, @@ -553,12 +552,8 @@ static void cups_async_callback(struct event_context *event_ctx, TALLOC_FREE(frame); if (tmp_pcap_cache) { bool ret; - /* We got a namelist, replace our local cache. */ - pcap_cache_destroy_specific(&local_pcap_copy); - local_pcap_copy = tmp_pcap_cache; - - /* And the systemwide pcap cache. */ - ret = pcap_cache_replace(local_pcap_copy); + /* replace the systemwide pcap cache. */ + ret = pcap_cache_replace(tmp_pcap_cache); if (!ret) DEBUG(0, ("failed to replace pcap cache\n")); @@ -600,35 +595,22 @@ bool cups_cache_reload(struct tevent_context *ev, talloc_free(cb_args); return false; } - if (!local_pcap_copy) { - /* We have no local cache, wait directly for - * async refresh to complete. - */ - DEBUG(10,("cups_cache_reload: sync read on fd %d\n", - *p_pipe_fd )); - - cups_async_callback(ev, NULL, - EVENT_FD_READ, - (void *)cb_args); - if (!local_pcap_copy) { - return false; - } - } else { - DEBUG(10,("cups_cache_reload: async read on fd %d\n", - *p_pipe_fd )); - - /* Trigger an event when the pipe can be read. */ - cache_fd_event = event_add_fd(ev, - NULL, *p_pipe_fd, - EVENT_FD_READ, - cups_async_callback, - (void *)cb_args); - if (!cache_fd_event) { - close(*p_pipe_fd); - TALLOC_FREE(cb_args); - return false; - } + + DEBUG(10,("cups_cache_reload: async read on fd %d\n", + *p_pipe_fd )); + + /* Trigger an event when the pipe can be read. */ + cache_fd_event = event_add_fd(ev, + NULL, *p_pipe_fd, + EVENT_FD_READ, + cups_async_callback, + (void *)cb_args); + if (!cache_fd_event) { + close(*p_pipe_fd); + TALLOC_FREE(cb_args); + return false; } + return true; } -- 1.7.1 From 5a0cf15f5879b8a3401d37e9d0eecac06a2130c9 Mon Sep 17 00:00:00 2001 From: David Disseldorp Date: Thu, 30 Dec 2010 15:58:48 +0100 Subject: [PATCH 2/2] s3-printing: fix cups pcap reload with no printers As reported in bug 7915. cups_async_callback() is called to receive new printcap data from a child process which requests the information from cupsd. Newly received printcap information is stored in a temporary printcap cache (tmp_pcap_cache). Once the child process closes the printcap IPC file descriptor, the system printcap cache is replaced with the newly populated tmp_pcap_cache, however this only occurs if tmp_pcap_cache is non null (has at least one printer). If the printcap cache is empty, which is the case when cups is not exporting any printers, the printcap cache is not replaced resulting in stale data. --- source3/printing/print_cups.c | 36 ++++++++++++++++++++++++------------ 1 files changed, 24 insertions(+), 12 deletions(-) diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c index d2df258..f294187 100644 --- a/source3/printing/print_cups.c +++ b/source3/printing/print_cups.c @@ -465,6 +465,7 @@ static void cups_async_callback(struct event_context *event_ctx, struct cups_async_cb_args *cb_args = (struct cups_async_cb_args *)p; int fd = cb_args->pipe_fd; struct pcap_cache *tmp_pcap_cache = NULL; + bool ret_ok = true; DEBUG(5,("cups_async_callback: callback received for printer data. " "fd = %d\n", fd)); @@ -482,6 +483,7 @@ static void cups_async_callback(struct event_context *event_ctx, if (ret != sizeof(namelen)) { DEBUG(10,("cups_async_callback: namelen read failed %d %s\n", errno, strerror(errno))); + ret_ok = false; break; } @@ -496,6 +498,7 @@ static void cups_async_callback(struct event_context *event_ctx, if (ret != sizeof(infolen)) { DEBUG(10,("cups_async_callback: infolen read failed %s\n", strerror(errno))); + ret_ok = false; break; } @@ -505,6 +508,7 @@ static void cups_async_callback(struct event_context *event_ctx, if (namelen) { name = TALLOC_ARRAY(frame, char, namelen); if (!name) { + ret_ok = false; break; } ret = sys_read(fd, name, namelen); @@ -515,6 +519,7 @@ static void cups_async_callback(struct event_context *event_ctx, if (ret != namelen) { DEBUG(10,("cups_async_callback: name read failed %s\n", strerror(errno))); + ret_ok = false; break; } DEBUG(11,("cups_async_callback: read name %s\n", @@ -525,6 +530,7 @@ static void cups_async_callback(struct event_context *event_ctx, if (infolen) { info = TALLOC_ARRAY(frame, char, infolen); if (!info) { + ret_ok = false; break; } ret = sys_read(fd, info, infolen); @@ -535,6 +541,7 @@ static void cups_async_callback(struct event_context *event_ctx, if (ret != infolen) { DEBUG(10,("cups_async_callback: info read failed %s\n", strerror(errno))); + ret_ok = false; break; } DEBUG(11,("cups_async_callback: read info %s\n", @@ -544,27 +551,32 @@ static void cups_async_callback(struct event_context *event_ctx, } /* Add to our local pcap cache. */ - pcap_cache_add_specific(&tmp_pcap_cache, name, info); + ret_ok = pcap_cache_add_specific(&tmp_pcap_cache, name, info); TALLOC_FREE(name); TALLOC_FREE(info); + if (!ret_ok) { + DEBUG(0, ("failed to add to tmp pcap cache\n")); + break; + } } TALLOC_FREE(frame); - if (tmp_pcap_cache) { - bool ret; - /* replace the systemwide pcap cache. */ - ret = pcap_cache_replace(tmp_pcap_cache); - if (!ret) + if (!ret_ok) { + DEBUG(0, ("failed to read a new printer list\n")); + pcap_cache_destroy_specific(&tmp_pcap_cache); + } else { + /* + * replace the system-wide pcap cache with a (possibly empty) + * new one + */ + ret_ok = pcap_cache_replace(tmp_pcap_cache); + if (!ret_ok) { DEBUG(0, ("failed to replace pcap cache\n")); - - /* Caller may have requested post cache fill callback */ - if (ret && cb_args->post_cache_fill_fn != NULL) { + } else if (cb_args->post_cache_fill_fn != NULL) { + /* Caller requested post cache fill callback */ cb_args->post_cache_fill_fn(cb_args->event_ctx, cb_args->msg_ctx); } - } else { - DEBUG(2,("cups_async_callback: failed to read a new " - "printer list\n")); } close(fd); TALLOC_FREE(cb_args); -- 1.7.1