diff --git a/wcfs/client/wcfs.cpp b/wcfs/client/wcfs.cpp
index cf96a990e95f10035af68db9867431cdee6fc44a..b052d788d478ccdde59704647ce0dd2c8b7bacbf 100644
--- a/wcfs/client/wcfs.cpp
+++ b/wcfs/client/wcfs.cpp
@@ -583,17 +583,21 @@ error _Conn::resync(zodb::Tid at) {
     atMuWLocked = false;
 
     // send watch updates to wcfs.
-    // the pinner is now running and will be able to serve pin requests triggered by out watch.
+    // the pinner is now running and will be able to serve pin requests triggered by our watch.
+    //
+    // update only fileh in "opened" state - for fileh in "opening" and
+    // "closing" states, watch setup is currently in-progress and performed by
+    // Conn.open and FileH.close correspondingly.
     for (auto fit : wconn._filehTab) {
         zodb::Oid  foid = fit.first;
-        //FileH    f    = fit.second;
+        FileH      f    = fit.second;
+
+        // XXX locking ok? (protected by wconn._mu ?)
+        if (f->_state != _FileHOpened)
+            continue;
 
-        // XXX need to lock f.mu because wconn.atMu is only R now.
-        // XXX need to coordinate with e.g. FileH.close -> "if f.state != CLOSING" ?
-        // XXX need to coordinate with e.g. Conn.open   -> "if f.state != OPENING" ?
+        // XXX need to lock f.mu because wconn.atMu is only R now. (???)
         string ack;
-        // XXX f._watchMu.lock() + unlock()
-        // XXX + recheck status before sending the watch?
         tie(ack, err) = wconn._wlink->sendReq(context::background(), fmt::sprintf("watch %s @%s", v(foid), v(at)));
         if (err != nil)
             return E(err);
@@ -687,7 +691,7 @@ retry:
             wconn._filehTab.erase(foid);
             wconn._mu.Unlock();
         }
-        f->_state = _FileHOpened;
+        f->_state = _FileHOpened;   // XXX move under wconn._mu ?
         f->_openReady.close();
     });
     wconn._mu.Unlock();
@@ -764,7 +768,8 @@ error _FileH::close() {
     });
 
     // fileh.close can be called several times. just return nil for second close.
-    if (fileh._closed)
+//  if (fileh._closed)
+    if (fileh._state >= _FileHClosing)
         return nil;
 
     // decref open count; do real close only when last open goes away.
@@ -777,6 +782,9 @@ error _FileH::close() {
     // last open went away - real close.
     xerr::Contextf E("%s: close f<%s>", v(wconn), v(fileh.foid));
 
+    ASSERT(fileh._state == _FileHOpened); // there can be no open-in-progress, because
+    fileh._state = _FileHClosing;         // .close() can be called only on "opened" fileh
+
     error err, eret;
     auto reterr1 = [&eret](error err) {
         if (eret == nil && err != nil)
@@ -785,6 +793,9 @@ error _FileH::close() {
 
     // XXX change all fileh.mmaps to cause EFAULT on any access after fileh.close
 
+    // XXX unlock wconn.mu
+    // XXX unlock f.mu
+
     // stop watching f          XXX ok under f.mu ?
     string ack;
     // XXX f._watchMu.lock() + unlock
diff --git a/wcfs/client/wcfs.h b/wcfs/client/wcfs.h
index 5282af08feed1304c076aef062988eeb1e557819..7af3127f987405b986d2ad023a74ebd962fbea0e 100644
--- a/wcfs/client/wcfs.h
+++ b/wcfs/client/wcfs.h
@@ -252,7 +252,7 @@ struct _FileH : object {
     bool                      _closed; // y after .close()
 
     // "watch <.foid> ..." requests we send to wcfs are serialized via FileH._watchMu
-    // XXX sync::Mutex        _watchMu;
+    // XXX sync::Mutex        _watchMu;     XXX kill
 
     // don't new - create via Conn.open
 private: