1
+ import asyncio
1
2
import os
2
3
import weakref
3
4
@@ -85,20 +86,21 @@ async def init(cls, context: BrowserContext, stagehand):
85
86
86
87
# Add event listener for new pages (popups, new tabs from window.open, etc.)
87
88
def handle_page_event (pw_page ):
88
- instance ._handle_new_page (pw_page )
89
+ # Playwright expects sync handler, so we schedule the async work
90
+ asyncio .create_task (instance ._handle_new_page (pw_page ))
89
91
90
92
context .on ("page" , handle_page_event )
91
93
92
94
return instance
93
95
94
- def _handle_new_page (self , pw_page : Page ):
96
+ async def _handle_new_page (self , pw_page : Page ):
95
97
"""
96
98
Handle new pages created by the browser (popups, window.open, etc.).
97
- This runs synchronously in the event handler context .
99
+ Uses the page switch lock to prevent race conditions with ongoing operations .
98
100
"""
99
-
100
- async def _async_handle ():
101
- try :
101
+ try :
102
+ # Use timeout to prevent indefinite blocking
103
+ async with asyncio . timeout ( 30 ) :
102
104
async with self .stagehand ._page_switch_lock :
103
105
self .stagehand .logger .debug (
104
106
f"Creating StagehandPage for new page with URL: { pw_page .url } " ,
@@ -109,26 +111,14 @@ async def _async_handle():
109
111
self .stagehand .logger .debug (
110
112
"New page detected and initialized" , category = "context"
111
113
)
112
- except Exception as e :
113
- self .stagehand .logger .error (
114
- f"Failed to initialize new page: { str (e )} " , category = "context"
115
- )
116
- import traceback
117
-
118
- self .stagehand .logger .error (
119
- f"Traceback: { traceback .format_exc ()} " , category = "context"
120
- )
121
-
122
- # Schedule the async work
123
- import asyncio
124
-
125
- try :
126
- loop = asyncio .get_running_loop ()
127
- loop .create_task (_async_handle ())
128
- except RuntimeError :
129
- # No event loop running, which shouldn't happen in normal operation
114
+ except asyncio .TimeoutError :
115
+ self .stagehand .logger .error (
116
+ f"Timeout waiting for page switch lock when handling new page: { pw_page .url } " ,
117
+ category = "context" ,
118
+ )
119
+ except Exception as e :
130
120
self .stagehand .logger .error (
131
- "No event loop available to handle new page" , category = "context"
121
+ f"Failed to initialize new page: { str ( e ) } " , category = "context"
132
122
)
133
123
134
124
def __getattr__ (self , name ):
0 commit comments